2015-05-01 2 views
1

В моем приложении я разместил два растровых изображения. Когда ориентация вертикальная, покажите первое изображение, если оно горизонтальное, покажите второе изображение. ИспользованиеОсвободить память после загрузки Bitmap

Log.i("log","Total memory " + title + " = " + (int) (Runtime.getRuntime().totalMemory()/1024)); 

Я обнаружил, что после того как я изменить ориентацию моего телефона несколько раз, общий объем памяти растет. Тем не менее, я ожидал бы, что память останется прежней, похоже, что программа не освобождает память.

Вот мой код

public Bitmap decodeSampledBitmapFromResource(int path, int reqWidth, int reqHeight, Context ctx){ 
    // Читаем с inJustDecodeBounds=true для определения размеров 
    final BitmapFactory.Options options = new BitmapFactory.Options(); 
    options.inJustDecodeBounds = true; 
    Bitmap b = BitmapFactory.decodeResource(ctx.getResources(), path, options); 

    // Вычисляем inSampleSize 
    options.inSampleSize = calculateInSampleSize(options, reqWidth, 
      reqHeight); 

    // Читаем с использованием inSampleSize коэффициента 
    options.inJustDecodeBounds = false; 
    return BitmapFactory.decodeResource(ctx.getResources(), path, options); 
} 

public static int calculateInSampleSize(BitmapFactory.Options options,int reqWidth, int reqHeight) { 
    // Реальные размеры изображения 
    Log.i("log", "inSampleSize" + reqWidth); 
    Log.i("log", "inSampleSize" + reqHeight); 
    final int height = options.outHeight; 
    Log.i("log", "height" + height); 
    final int width = options.outWidth; 
    Log.i("log", "height" + width); 
    int inSampleSize = 1; 

    if (height > reqHeight || width > reqWidth) { 

     final int halfHeight = height/2; 
     final int halfWidth = width/2; 

     // Вычисляем наибольший inSampleSize, который будет кратным двум 
     // и оставит полученные размеры больше, чем требуемые 
     while ((halfHeight/inSampleSize) > reqHeight 
       && (halfWidth/inSampleSize) > reqWidth) { 
      inSampleSize *= 2; 
      Log.i("log", "inSampleSize" + inSampleSize); 
     } 
    } 

    return inSampleSize; 
} 

private void readImage(int draw) { 

    //int px = getResources().getDimensionPixelSize(draw); 
    int pxW = displaymetrics.widthPixels; 
    int pxH = displaymetrics.heightPixels; 
    ***if(bitmap != null){ 
     bitmap.recycle(); 
     bitmap = null; 
    }*** 

    bitmap = decodeSampledBitmapFromResource(draw, My_px_W, My_px_H, this); 
    ivStart.setImageBitmap(bitmap); 

} 

Вот OnCreate

if(getResources().getConfiguration().orientation == Configuration.ORIENTATION_PORTRAIT) { 

     My_px_W = 200; 
     My_px_H = 150; 

     readImage(R.drawable.im2); 



     logMemory("'vertical'"); 
    } 
    else if (getResources().getConfiguration().orientation == Configuration.ORIENTATION_LANDSCAPE) { 

     My_px_W = 400; 
     My_px_H = 200; 

     readImage(R.drawable.s2); 
     logMemory("'horizontal'"); 

    } 
+0

@TravisHeeter Как вы русский код в редактировать? – kenorb

+0

Просто убедитесь, что вы не слишком часто это делаете - сбор мусора дорогой! По крайней мере, если вы делаете это с несколькими растровыми изображениями каждый раз, когда устройство меняет ориентацию, убедитесь, что вы используете только одну коллекцию. – Floegipoky

+0

Когда я остаюсь в горизонтальном (установите первое изображение), у меня есть первый подсчет памяти (27160), когда я остаюсь в вертикальном (установите второе изображение), моя память растет (31032), затем я снова остаюсь в горизонтальной плоскости (задаю первое изображение) и моя память больше растет (39432). – Foxstrot

ответ

1

Вам нужно позвонить System.gc() после recycle называется, если вы хотите, чтобы быть немедленно освобожден.

Рециркулировать на свое собственное недостаточно, поскольку сборщик мусора не вызывается.

Освободите родной объект, связанный с этим растровым изображением, и очистите ссылку на данные пикселя . Это не освободит данные пикселя синхронно; он просто позволяет собирать мусор, если нет . Растровое изображение отмечено как «мертвое», то есть выдает исключение, если вызывается getPixels() или setPixels(), а ничего не рисует. Эта операция не может быть отменена, поэтому она должна быть вызвана , если вы уверены, что дальнейших применений для растрового изображения больше нет. Это расширенный вызов и обычно не нужно называть , так как нормальный процесс GC освободит эту память, если нет дополнительных ссылок на это растровое изображение.

+0

Благодарим за ответ Боян, но System.gc() не освобождает память моего изображения. Когда я остаюсь в горизонтальном (установите первое изображение), у меня есть первый подсчет памяти (27160), когда я остаюсь в вертикальном (установите второе изображение), моя память вырастает (31032), затем я снова остаюсь в горизонтальном (установите первое изображение) и мой память больше растет (39432). – Foxstrot

+0

Тогда мой друг, у вас есть утечка памяти! –

+0

нет действительно. System.gc() - это всего лишь намек. он не гарантирует ничего. и это никогда не должно быть необходимым в производственном коде. прочитайте документы на этом, прежде чем предлагать это как ответ – dabluck

0

Вы должны позвонить bitmap.recycle(), а затем вызвать System.gc()

Убедитесь, что вы не используете один и тот же битовый массив после рециркуляции вызова()

+0

Когда я остаюсь в горизонтальном (установите первое изображение), у меня есть первый подсчет памяти (27160), когда я остаюсь в вертикальном (установите второе изображение), моя память растет (31032) , то я снова остаюсь в горизонтальном (установите первое изображение), и моя память больше растет (39432). – Foxstrot

Смежные вопросы