`

(原创)Android手动回收bitmap,引发Canvas: trying to use a recycled bitmap处理

阅读更多

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

 

 java.lang.RuntimeException: Canvas: trying to use a recycled bitmap android.graphics.Bitmap@41de4380
     at android.graphics.Canvas.throwIfRecycled(Canvas.java:1026)
     at android.graphics.Canvas.drawBitmap(Canvas.java:1127)
     at android.graphics.drawable.BitmapDrawable.draw(BitmapDrawable.java:393)
     at android.widget.ImageView.onDraw(ImageView.java:961)
     at android.view.View.draw(View.java:13458)
     at android.view.View.draw(View.java:13342)
     at android.view.ViewGroup.drawChild(ViewGroup.java:2929)
     at android.view.ViewGroup.dispatchDraw(ViewGroup.java:2799)
     at android.view.View.draw(View.java:13461)
     at android.view.View.draw(View.java:13342)

 

 

图片手动回收部分代码:

 

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

 

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

 

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

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

import android.content.Context;
import android.graphics.Canvas;
import android.util.AttributeSet;
import android.widget.ImageView;

/**
 * 重写ImageView,避免引用已回收的bitmap异常
 * 
 * @author zwn
 * 
 */
public class MyImageView extends ImageView {

	public MyImageView (Context context, AttributeSet attrs) {
		super(context, attrs);
	}

	@Override
	protected void onDraw(Canvas canvas) {
		try {
			super.onDraw(canvas);
		} catch (Exception e) {
			System.out
					.println("MyImageView  -> onDraw() Canvas: trying to use a recycled bitmap");
		}
	}

}

 

 

分享到:
评论
3 楼 Escalade 2018-06-08  
果然如此,这是什么原因造成的呢??为何捕获异常后就不闪退了呢??我是在RecyclerView的Adapter中第一次设置Adapter是没问题的,在重新设置就闪退了,重写onDraw方法就可以重复设置了。这是为何???
2 楼 situee 2013-10-16  
“图片手动回收” 应该要 softReference.clear(); 和 imageCache.remove(key);
另外还要检查有没有View在用这个bitmap, 否则会出Exception "trying to use a recycled bitmap"
1 楼 IT学习 2013-07-29  
这个思路不错,不过要使用到自定义控件中,最好还要把另外两个构造方法写上!
谢谢了!

相关推荐

Global site tag (gtag.js) - Google Analytics