Android - избегайте утечек памяти для изображений, извлеченных из галереи

1

Я должен позволить пользователю открыть конкретный альбом из своей галереи и позволить им делать что-то с изображениями.

Чтобы получить изображение из альбома, я использую:
Bitmap bitmap = MediaStore.Images.Media.getBitmap(contentResolver, uri).

Все работает отлично, за исключением того факта, что если в альбоме много фотографий, он заканчивает вымывание OutOfMemoryException.
Теперь я знаю, как смягчить эту проблему на основе рекомендаций Android, но проблема в том, что я уже getBitmap() исходный getBitmap() с помощью getBitmap()

Итак, есть ли возможность получить изображение в формате массива байтов или формат входного потока и масштабировать его, прежде чем назначать его в памяти, чтобы избежать утечек памяти? (точно так же, как советы по рекомендациям Android)

Теги:
android-emulator
android-layout
android-intent
android-widget

2 ответа

0
Лучший ответ

Итак, имея изображение Uri в моих руках, я хотел получить его InputStream и уменьшить изображение перед тем, как назначить его в памяти, чтобы избежать OutOfMemoryException

Решение:
Чтобы получить InputStream из Uri, вы должны вызвать это:

InputStream stream = getContentResolver().openInputStream(uri);

Затем, следуя рекомендациям Android по эффективному загрузке растровых изображений, вам просто нужно вызвать BitmapFactory.decodeStream() и передать BitmapFactory.Options в качестве параметра.

Полный исходный код:

imageView = (ImageView) findViewById(R.id.imageView);

Uri uri = Uri.parse("android.resource://com.testcontentproviders/drawable/"+R.drawable.test_image_large);
Bitmap bitmap=null;
    try {
        InputStream stream = getContentResolver().openInputStream(uri);
        bitmap=decodeSampledBitmapFromStream(stream, 150, 100);
    } catch (FileNotFoundException e) {
        e.printStackTrace();
    }

imageView.setImageBitmap(bitmap);

Вспомогательные методы:

public static Bitmap decodeSampledBitmapFromStream(InputStream stream,
            int reqWidth, int reqHeight) {

    // First decode with inJustDecodeBounds=true to check dimensions
    final BitmapFactory.Options options = new BitmapFactory.Options();
    options.inJustDecodeBounds = true;
    BitmapFactory.decodeStream(stream, null, options);

    // Calculate inSampleSize
    options.inSampleSize = calculateInSampleSize(options, reqWidth,
                reqHeight);

    // Decode bitmap with inSampleSize set
    options.inJustDecodeBounds = false;
    return BitmapFactory.decodeStream(stream, null, options);
}

public static int calculateInSampleSize(BitmapFactory.Options options,
            int reqWidth, int reqHeight) {
    // Raw height and width of image
    final int height = options.outHeight;
    final int width = options.outWidth;
    int inSampleSize = 1;

    if (height > reqHeight || width > reqWidth) {
        if (width > height) {
            inSampleSize = Math.round((float) height / (float) reqHeight);
        } else {
            inSampleSize = Math.round((float) width / (float) reqWidth);
        }
    }
    return inSampleSize;
}
0

Вы уже определили очень хорошее решение. Если вы хотите пропустить шаг потянув изображение в Bitmap через MediaStore, попробуйте использовать ImageView.setImageUri().

  • 0
    Привет, спасибо за комментарий. Попытка передать Uri в ImageView перед масштабированием также вызывает OutOfMemoryException, если изображение слишком велико. Но вы открыли для меня новую альтернативу, и на основе этого изображения Uri теперь я могу получить InputStream и уменьшить изображение. Я скоро выложу решение.

Ещё вопросы

Сообщество Overcoder
Наверх
Меню