美文网首页
Android Bitmap Pool

Android Bitmap Pool

作者: VictorLiang | 来源:发表于2017-03-19 15:46 被阅读286次

在图片使用较多的应用中,每个图片的展示至少要Decode一次。由于图片比较占内存,所以内存分配/释放的频率会提高。也就是由于allocation 导致的GC(GC_FOR_ALLOC)出现的频率会很高。众所周至GC可能会导致UI卡顿,所以说图片多的应用非常容易出现卡顿。

为了解决这个问题,Android中提供了Bitmap Pool的概念 (参考资料:Re-using Bitmaps)。

使用Bitmap Pool的一种方式是使用inBitmap()。
话不多说,直接看代码。

Bitmap bitmapOne = BitmapFactory.decodeFile(filePathOne);
imageView.setImageBitmap(bitmapOne);
final BitmapFactory.Options options = new BitmapFactory.Options();
options.inJustDecodeBounds = true;
BitmapFactory.decodeFile(filePathTwo, options);
if (canUseInBitmap(bitmapOne, options)) { 
    //判断是否可用inBitmap
    options.inMutable = true;
    options.inBitmap = bitmapOne;
}
options.inJustDecodeBounds = false;
Bitmap bitmapTwo = BitmapFactory.decodeFile(filePathTwo, options);
imageView.setImageBitmap(bitmapTwo);

如何判断是否能够设置使用inBitmap()呢?就得看官方给的限制条件:

  1. API 11-18 要求Bitmap大小完全一致, 并且inSampleSize必须是1 官方文档
  2. API 19+ (Android 4.4及以后) 要求被重用的Bitmap所占大小要大于等于要加载的Bitmap

判断是否能够使用inBitMap()

public static boolean canUseInBitmap(Bitmap reuseBitmap, BitmapFactory.Options targetOptions) {

        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) {
            // 4.4+
            int width = targetOptions.outWidth / targetOptions.inSampleSize;
            int height = targetOptions.outHeight / targetOptions.inSampleSize;
            int byteCount = width * height * getDim(reuseBitmap.getConfig());

            try {
                return byteCount <= reuseBitmap.getAllocationByteCount();
            } catch (NullPointerException e) {
                return byteCount <= reuseBitmap.getHeight() * reuseBitmap.getRowBytes();
            }
        }
        // API 18 前
        return reuseBitmap.getWidth() == targetOptions.outWidth
                && reuseBitmap.getHeight() == targetOptions.outHeight
                && targetOptions.inSampleSize == 1;
    }
    private static int getDim(Bitmap.Config config) {
        if (config == null) {
            return 4;
        }
        switch (config) {
            case ALPHA_8:
            default:
                return 1;
            case RGB_565:
            case ARGB_4444:
                return 2;
            case ARGB_8888:
                return 4;
        }
    }

注意事项:

  1. 如果尝试重用不可被复用Bitmap,decode方法会返回null并抛出IllegalArgumentException。
  2. 被复用的Bitmap必须要求设置为mutable,decode返回的新的bitmap也是mutable。

最后,一个好消息 and 一个坏消息:

好消息:
Glide, Fresco等比较新的图片加载库,已经完全支持inBitmap了,一般情况下不需要手动的配置。
坏消息:
目前我们产品中使用的UIL不支持inBitmap。

相关文章

网友评论

      本文标题:Android Bitmap Pool

      本文链接:https://www.haomeiwen.com/subject/jromnttx.html