在圖片使用較多的應(yīng)用中,每個(gè)圖片的展示至少要Decode一次徘意。由于圖片比較占內(nèi)存懂昂,所以內(nèi)存分配/釋放的頻率會(huì)提高。也就是由于allocation 導(dǎo)致的GC(GC_FOR_ALLOC)出現(xiàn)的頻率會(huì)很高翅楼。眾所周至GC可能會(huì)導(dǎo)致UI卡頓尉剩,所以說圖片多的應(yīng)用非常容易出現(xiàn)卡頓。
為了解決這個(gè)問題毅臊,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);
如何判斷是否能夠設(shè)置使用inBitmap()呢?就得看官方給的限制條件:
- API 11-18 要求Bitmap大小完全一致, 并且inSampleSize必須是1 官方文檔
- 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;
}
}
注意事項(xiàng):
- 如果嘗試重用不可被復(fù)用Bitmap蚯撩,decode方法會(huì)返回null并拋出IllegalArgumentException础倍。
- 被復(fù)用的Bitmap必須要求設(shè)置為mutable,decode返回的新的bitmap也是mutable胎挎。
最后沟启,一個(gè)好消息 and 一個(gè)壞消息:
好消息:
Glide, Fresco等比較新的圖片加載庫犹菇,已經(jīng)完全支持inBitmap了德迹,一般情況下不需要手動(dòng)的配置。
壞消息:
目前我們產(chǎn)品中使用的UIL不支持inBitmap揭芍。