在Android 2.3.3或者更低版本下的时候,对于释放Bitmap的内存调用recycle()方法是必要的。否则在加载大量Bitmap的时候很容易就造成 OutOfMemoryError
。recycle()能够及时的释放Bitmap内存。
注意:只有在不用Bitmap的时候才能调用recycle(),否则会造成Canvas: trying to use a recycled bitmap问题。
内存管理的全部实现有点复杂,但是把复杂的问题拆分开来作就非常简单了,在本章中只是实现能够自己释放内存的
BitmapDrawable。代码如下:
public static final String TAG = "RecyclingBitmapDrawable";
/**
* 正在使用(显示)的计数
* */
private int mDisplayRefCounts = 0;
/**
* 正在被缓存的计数
* */
private int mCacheRefCounts = 0;
/**
* 是否已经被显示过了
* */
private boolean mHasDisplay = false;
public RecyclingBitmapDrawable(Resources res, Bitmap bitmap) {
super(res, bitmap);
// TODO Auto-generated constructor stub
}
/**
*
* 设置BitmapDrawable是否正在显示,如果显示这里传入true,如果不再显示了这里传入 false
*
* @param isDisplayed
* 是否显示
* */
public void setIsDisplayed(boolean isDisplayed) {
synchronized (this) { // 保持同步,防止多个线程修改数据时造成 Canvas: trying to use a
// recycled bitmap或者 OutOfMemoryError
if (isDisplayed) {
mDisplayRefCounts++;
mHasDisplay = true;
} else {
mDisplayRefCounts--;
}
}
// 这个不需要同步
checkState();
}
/**
* 设置BitmapDrawable是否正在被缓存,如果被缓存了这里传入true,否则传入 false
* */
public void setIsCached(boolean isCached) {
synchronized (this) {
if (isCached) {
mCacheRefCounts++;
} else {
mCacheRefCounts--;
}
}
checkState();
}
// 检测显示和缓存状态,如果计数都为0的话,就释放Bitmap
private void checkState() {
synchronized (this) {
if (mDisplayRefCounts <= 0 && mCacheRefCounts <= 0 && mHasDisplay && hasVildBitmap()) {
if (BuildConfig.DEBUG) {
System.out.println(TAG + "--" + "释放不再使用的Bitmap");
getBitmap().recycle();
}
}
}
}
// 检测Bitmap是否可用,Bitmap不能为空,并且没有被释放
private boolean hasVildBitmap() {
synchronized (this) {
Bitmap bitmap = getBitmap();
return bitmap != null && !bitmap.isRecycled();
}
}
用 BitmapFactory.Options.inBitmap
这个字段,具体内容查看http://blog.csdn.net/hello_tree/article/details/11732293
在这里总结下android不同版本对于图片存储和释放的不同之处:
①在过去通过 SoftReference或者WeakReference来缓存Bitmap,但是从Android 2.3(API Level 9)开始,就不推荐
使用了,因为从2.3开始垃圾回收器会非常积极的回收 soft/weak 引用,这使得这样缓存相当无效。
②在Android3.0(API Level 11)之前,bitmap的像素数据是存储在 in native memory 本地的,是和Bitmap自己分
开存储的,Bitmap存储在 Dalvik heap中,Bitmap的像素数据(在 native memeory中)的释放是不可预见的,这
可能导致程序内存不够从而崩溃。在Android 3.0(API Level 11)开始,Bitmap的像素数据和相关的Bitmap一块存储
在 Dalvik heap中。
③在Android 3.0(API Level 11)之前,如果加载大量bitmap数据在你的app 中时,应该在不用Bitmap的时候调用
recycle()方法,recycle()方法允许app尽快的回收内存(由于在 3.0之前Bitmap的后台像素数据和Bitmap是分开存
储的,并且后台数据的释放是不可预见的,所以通过手动调用Bitmap的recycle()方法来释放内存)。
④在Android 3.0(API Level 11)和之后的版本中,由于bitmap的后台像素数据和它本身一块存储在虚拟机堆(Dalvik
heap)中,所
以不用手动调用Bitmap的recycle()方法,当没有引用指向Bitmap的时候,垃圾回收器会自动释放bitmap的内存。