如何有效地处理位图列表并避免内存不足错误

时间:2016-10-22 13:22:18

标签: android performance android-bitmap

我正在开发一个Android应用程序,我必须在那里处理很多位图。有时应用程序因内存不足而崩溃。

所以我有一个自定义对象(Song类),我有像标题,艺术家,链接和位图这样的字段。我从音频流中获取专辑封面,并将该位图分配到相关对象的字段中。

以下是获取专辑封面位图的代码

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 && (halfWidth / inSampleSize) >= reqWidth) {
            inSampleSize *= 2;
        }
    }

    return inSampleSize;
}

1 个答案:

答案 0 :(得分:1)

您需要使用库来加载图像。

Glide是一个用于加载图像的神奇库。

首先,依赖是

将这两个放在build.gradle中

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

然后在您的适配器中,您需要加载图像:

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

您也可以根据自己的需要进一步定制,只需访问他们的Github Page

Future Studio也有很好的自定义教程。