解决Bitmap recycle异常:Canvas: trying to use a recycled bitmap android.graphics.Bitmap

Bitmap回收异常:Canvas: trying to use a recycled bitmap android.graphics.Bitmap解决

今天测试程序发现程序偶尔会异常崩溃,后来发现可能是有3个Bitmap对象没有回收,占了一部分内存,在手机内存不多的时候程序就崩掉了,

后来对Bitmap对象统一进行了isRecycled,这样能加速系统对无用资源的回收,但发现还是有问题:Canvas: trying to use a recycled bitmap android.graphics.Bitmap,

最后的解决办法是在isRecycled前对Bitmap进行一个非空和是否isRecycled的判断,问题搞定。

注:网友说可以不必回收gc会自动回收,看了一些资料后总结recycle是native方法,不是java代码产生的,回收还是有必要的。

在做Android的开发的时候,在ListView 或是 GridView中需要加载大量的图片,为了避免加载过多的图片引起OutOfMemory错误,设置了一个图片缓存列表 Map<String, SoftReference<Bitmap>> imageCache , 并对其进行维护,在图片加载到一定数量的时候,就手动回收掉之前加载图片的bitmap,此时就引起了如下错误:

  1. java.lang.RuntimeException: Canvas: trying to use a recycled bitmap android.graphics.Bitmap@41de4380  
  2.     at android.graphics.Canvas.throwIfRecycled(Canvas.java:1026)  
  3.     at android.graphics.Canvas.drawBitmap(Canvas.java:1127)  
  4.     at android.graphics.drawable.BitmapDrawable.draw(BitmapDrawable.java:393)  
  5.     at android.widget.ImageView.onDraw(ImageView.java:961)  
  6.     at android.view.View.draw(View.java:13458)  
  7.     at android.view.View.draw(View.java:13342)  
  8.     at android.view.ViewGroup.drawChild(ViewGroup.java:2929)  
  9.     at android.view.ViewGroup.dispatchDraw(ViewGroup.java:2799)  
  10.     at android.view.View.draw(View.java:13461)  
  11.     at android.view.View.draw(View.java:13342)  

图片手动回收部分代码:

  1. Bitmap removeBitmap = softReference.get();  
  2. if(removeBitmap != null && !removeBitmap.isRecycled()){  
  3.     removeBitmap.recycle(); //此句造成的以上异常  
  4.     removeBitmap = null;  
  5. }  

网上有好多人说应该把recycle()去掉,个人认为去掉后会引起内存持续增长,虽然将bitmap设置为了null,但是系统并没有对其进行真正的回收,仍然占有内存,即是调用了System.gc() 强制回后以后,内存仍然没有下去,如果依靠内存达到上限时系统自己回收的话,个人觉得太晚了,已经对应用造成了影响,应用应该是比较卡了,所以还是赞同加上bitmap.recycle() ,但是又会引起  Canvas: trying to use a recycled bitmap 异常,困扰了很久,开始尝试从其它方面着手来解决这个问题,即然是异常就应该能够捕获到,但是在Adapter里的getView()方法里进行捕获的时候,时机晚了,没有捕获到。现在换到在ImageView的onDraw()里进行捕获,上面的异常能够捕获。

解决方法(继承ImageView 重写onDraw()方法,捕获异常):

在重写onDraw()方法中,其实什么都没有做,只是添加了一个异常捕获,即可捕捉到上面的错误

  1. import android.content.Context;  
  2. import android.graphics.Canvas;  
  3. import android.util.AttributeSet;  
  4. import android.widget.ImageView;  
  5.   
  6. /** 
  7.  * 重写ImageView,避免引用已<strong>回收</strong>的bitmap异常 
  8.  *  
  9.  * @author zwn 
  10.  *  
  11.  */  
  12. public class MyImageView extends ImageView {  
  13.   
  14.     public MyImageView (Context context, AttributeSet attrs) {  
  15.         super(context, attrs);  
  16.     }  
  17.   
  18.     @Override  
  19.     protected void onDraw(Canvas canvas) {  
  20.         try {  
  21.             super.onDraw(canvas);  
  22.         } catch (Exception e) {  
  23.             System.out  
  24.                     .println("MyImageView  -> onDraw() Canvas: trying to use a recycled bitmap");  
  25.         }  
  26.     }  
  27.   
  28. }  
在开发项目的时候 出现了Canvas: trying to use a recycled bitmap android.graphics.Bitmap一个异常。在网上看了很多资料。有的说传入图片和新的bitmap图片分辨率一样,强行改变图片的分辨率就不会出现异常了。可是问题还是解决不了。后来看bitmap.recycle()的官方介绍:

Free the native object associated with this bitmap, and clear the reference to the pixel data. This will not free the pixel data synchronously; it simply allows it to be garbage collected if there are no other references. The bitmap is marked as "dead", meaning it will throw an exception if getPixels() or setPixels() is called, and will draw nothing. This operation cannot be reversed, so it should only be called if you are sure there are no further uses for the bitmap. This is an advanced call, and normally need not be called, since the normal GC process will free up this memory when there are no more references to this bitmap. 

大体意思是这个函数不是必须要调用的。
后来我直接把代码改成了
if (bitmap != null && !bitmap.isRecycled()) 

     bitmap=null;
}     

直接给他赋空了。最后就解决了。出现了这个问题的朋友可以试试这种方法。或许能够帮到你们。。。
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值