Android Bitmap内存管理,解决内存溢出问题(1)之自定义BitmapDrawable

来源:互联网 发布:淘宝买二手怎么交易 编辑:程序博客网 时间:2024/05/16 09:39

在Android 2.3.3或者更低版本下的时候,对于释放Bitmap的内存调用recycle()方法是必要的。否则在加载大量Bitmap的时候很容易就造成 OutOfMemoryError 。recycle()能够及时的释放Bitmap内存

注意:只有在不用Bitmap的时候才能调用recycle(),否则会造成Canvas: trying to use a recycled bitmap问题。


内存管理的全部实现有点复杂,但是把复杂的问题拆分开来作就非常简单了,在本章中只是实现能够自己释放内存的


BitmapDrawable。代码如下:

public static final StringTAG= "RecyclingBitmapDrawable";/** * 正在使用(显示)的计数 * */private intmDisplayRefCounts= 0;/** * 正在被缓存的计数 * */private intmCacheRefCounts= 0;/** * 是否已经被显示过了 * */private booleanmHasDisplay= 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或者 OutOfMemoryErrorif (isDisplayed) {mDisplayRefCounts++;mHasDisplay = true;} else {mDisplayRefCounts--;}}// 这个不需要同步checkState();}/** * 设置BitmapDrawable是否正在被缓存,如果被缓存了这里传入true,否则传入 false * */public void setIsCached(boolean isCached) {synchronized (this) {if (isCached) {mCacheRefCounts++;} else {mCacheRefCounts--;}}checkState();}// 检测显示和缓存状态,如果计数都为0的话,就释放Bitmapprivate 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();}}


在这里不得不说下在 Android2.3.3或更高版本上的Bitmap内存处理,为了更有效的利用Bitmap的内存,要充分利

用 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的内存。




原创粉丝点击