Как эффективно обрабатывать список растровых изображений и избежать ошибки нехватки памяти

#android #performance #android-bitmap

#Android #Производительность #android-bitmap

Вопрос:

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

Итак, у меня есть пользовательский объект (класс песни), и там у меня есть такие поля, как название, исполнитель, ссылка и растровое изображение. Я получаю обложку альбома из аудиопотока и назначаю это растровое изображение в поле соответствующего объекта.

Вот код для получения растрового изображения обложки альбома,

 public static CustomBitmap downloadAudioCover(Context context, final String url) {
    final MediaMetadataRetriever metaRetriever = new MediaMetadataRetriever();
    try {
        metaRetriever.setDataSource(url, new HashMap<String, String>());
        final byte[] art = metaRetriever.getEmbeddedPicture();
        int width = context.getResources().getDimensionPixelSize(R.dimen.image_audio_cover_width);
        int height = context.getResources().getDimensionPixelSize(R.dimen.image_audio_cover_height);
        CustomBitmap customBitmap = new CustomBitmap();
        customBitmap.setBitmap(decodeSampledBitmapFromResource(art, width, height));
        return customBitmap;
    } catch (Exception e) {
        return null;
    }
}
  

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

Проблема в том, что я получаю примерно 50 песен, что означает, что мне нужно хранить 50 объектов с 50 растровыми изображениями.

Для отображения этих данных я использую RecyclerView.

Поскольку у меня изначально нет растровых изображений, мне нужно вызывать этот метод выше для каждой отдельной песни. Итак, сначала я получаю песни (без растрового изображения), и после того, как я извлекаю все песни, я просматриваю список массива, чтобы получить растровые изображения. Как только я получил все растровые изображения, я вызываю метод notifyDataSetChanged на адаптере.

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

* Является ли получение растрового изображения внутри onBindViewHolder и установка значения imageview без присвоения объекту хорошим решением для этого?

Спасибо.

Примечание: это код для выборки растровых изображений

 private static Bitmap decodeSampledBitmapFromResource(byte[] arr, int reqWidth, int reqHeight) {
    // First decode with inJustDecodeBounds=true to check dimensions
    final BitmapFactory.Options options = new BitmapFactory.Options();
    options.inJustDecodeBounds = true;
    BitmapFactory.decodeByteArray(arr, 0, arr.length, options);

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

    // Decode bitmap with inSampleSize set
    options.inJustDecodeBounds = false;
    return BitmapFactory.decodeByteArray(arr, 0, arr.length, options);
}


   private 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) {
        final int halfHeight = height / 2;
        final int halfWidth = width / 2;

        // Calculate the largest inSampleSize value that is a power of 2 and keeps both
        // height and width larger than the requested height and width.
        while ((halfHeight / inSampleSize) >= reqHeight amp;amp; (halfWidth / inSampleSize) >= reqWidth) {
            inSampleSize *= 2;
        }
    }

    return inSampleSize;
}
  

Комментарии:

1. вы пробовали Glide ?

2. У меня нет. Я использую универсальный загрузчик изображений в этом приложении для загрузки других изображений. но, как вы можете видеть, я получаю растровое изображение из аудиопотока и устанавливаю его в imageview, используя только метод setImageBitmap.

3. Используйте библиотеку загрузки изображений Fresco Facebook. Это автоматически устраняет все проблемы с ООМ, перерабатывая все изображения и очищая память самостоятельно. По моему собственному опыту, UIL вызывает множество проблем с ООМ. Используйте Fresco, и вы будете счастливы: P

Ответ №1:

Вам нужно использовать библиотеку для загрузки изображений.

Glide — потрясающая библиотека для загрузки изображений.

Прежде всего, зависимость

поместите эти два в свой build.gradle

 compile 'com.github.bumptech.glide:glide:3.7.0'
  

и затем в вашем адаптере, куда вы загружаете изображение, все, что вам нужно сделать, это:

 Glide
    .with(context)
    .load(AudioArt)
    .into(yourImageView);
  

Вы также можете настроить его в соответствии со своими потребностями, просто посетите их страницу на Github.

У Future Studio также есть отличное руководство по его настройке.

Комментарии:

1. получает ли растровое изображение аудиопоток?? я не думаю??

2. Это так. Переменная AudioArt может быть byte[] . Удачи!)