作者:BuauOoO_987 | 来源:互联网 | 2023-01-18 11:04
Bitmap第一印象就是内存土豪,这样就造就了它天生的任性。在2.2以及之前的Android是单线程垃圾回收器,在2.3以后才是并发的回收,且在3.0以前Bitmap的存储方式也是放开的Bi
Bitmap第一印象就是内存"土豪",这样就造就了它天生的任性。在2.2以及之前的Android是单线程垃圾回收器,在2.3以后才是并发的回收,且在3.0以前Bitmap的存储方式也是放开的Bitmap对象存储在Dalvik heap中,而Bitmap对象的像素数据则存储在Native Memory(本地内存)中或者说Derict Memory(直接内存)中,这我们在回收bitmap的时候很容报"Canvas: trying to use a recycled bitmap"错误而导致了程序奔溃,在3.0开始并发回收但是任然会出现内存不足的情况,列出一些在图片中我们常使用的一些方法。
1、LruCache缓存
mMemoryCache = new LruCache(mCacheParams.memCacheSize) {
/**
* Notify the removed entry that is no longer being cached
*/
@Override
protected void entryRemoved(boolean evicted, String key,
BitmapDrawable oldValue, BitmapDrawable newValue) {
if (RecyclingBitmapDrawable.class.isInstance(oldValue)) {
// The removed entry is a recycling drawable, so notify it
// that it has been removed from the memory cache
((RecyclingBitmapDrawable) oldValue).setIsCached(false);
} else {
// The removed entry is a standard BitmapDrawable
if (Utils.hasHoneycomb()) {
// We're running on Honeycomb or later, so add the bitmap
// to a SoftRefrence set for possible use with inBitmap later
mReusableBitmaps.add(new SoftReference(oldValue.getBitmap()));
}
}
}
/**
* Measure item size in kilobytes rather than units which is more practical
* for a bitmap cache
*/
@Override
protected int sizeOf(String key, BitmapDrawable value) {
final int bitmapSize = getBitmapSize(value) / 1024;
return bitmapSize == 0 ? 1 : bitmapSize;
}
};
mReusableBitmaps这个用于被寄出去的bitmap,用于后面Options.inBitmap中使用。那么是怎么使用的呢?
2、Options进行缩放
Options.inSampleSize 我们通过改变该值来起到缩放当前的bitmap作用,通过设置options.inMutable =true然后按从mReusableBitmaps中找符合要求且被回收的bitmap从而设置到options.inBitmap中,这果这个字段被设置了,则解码时会把重用这个字段所引用的那张Bitmap,避免重新分配内存。
private static boolean canUseForInBitmap(
Bitmap candidate, BitmapFactory.Options targetOptions) {
int width = targetOptions.outWidth / targetOptions.inSampleSize;
int height = targetOptions.outHeight / targetOptions.inSampleSize;
return candidate.getWidth() == width && candidate.getHeight() == height;
}
3、DiskLruCache进行SD卡缓存
先进行简单的初始化操作:
mDiskLruCache = DiskLruCache.open(diskCacheDir, 1, 1,mCacheParams.diskCacheSize);
从diskLruCache中读取数据
final DiskLruCache.Snapshot snapshot = mDiskLruCache.get(key);
if (snapshot != null) {
if (BuildConfig.DEBUG) {
Log.d(TAG, "Disk cache hit");
}
inputStream = snapshot.getInputStream(DISK_CACHE_INDEX);
if (inputStream != null) {
FileDescriptor fd = ((FileInputStream) inputStream).getFD();
// Decode bitmap, but we don't want to sample so give
// MAX_VALUE as the target dimensions
bitmap = ImageResizer.decodeSampledBitmapFromDescriptor(
fd, Integer.MAX_VALUE, Integer.MAX_VALUE, this);
}
}
最后:对Bitmap我们在3.0以前如果已经不会再使用了,我们需要进行recycle避免再内存中一直占据着空间。在3.0以后我们需要重复使用在LruCache中被挤出去的bitmap,通过有效的缩放bitmap,避免宝贵的手机内存被占用殆尽。简单笔记一下!