彻底解决 trying to use a recycled bitmap android.graphics.Bitmap@41d之道

发布时间:2017-3-14 8:53:28编辑:www.fx114.net 分享查询网我要评论
本篇文章主要介绍了"彻底解决 trying to use a recycled bitmap android.graphics.Bitmap@41d之道",主要涉及到彻底解决 trying to use a recycled bitmap android.graphics.Bitmap@41d之道方面的内容,对于彻底解决 trying to use a recycled bitmap android.graphics.Bitmap@41d之道感兴趣的同学可以参考一下。



在最近一个项目中,因为要使用AnimationDrawable进行动画播放,图片质量都比较大,而且播放的频率会很多,开发的行车记录仪的内存又有限,刚开始并没有将Bitmap recycle掉,所以出现了OOM的异常。为了解决内存溢出问题,在退出当前页面的时候,将Bitmap recycle掉。但是在此又遇到了另外一个问题,退出当前界面再进入这个页面的时候会报出   trying to use a recycled bitmap android.graphics.Bitmap@41d的异常。

此后看了很多文章,但是都并不能真正的解决这个问题,只能从源码查起了。

分析问题出现原因是在我们加载drawable的时候可能bitmap recycle后,被再次使用,所以导致此问题的出现。跟踪一下源代码 getResource(context).getDrawable(id)==继续进入代码==>loadDrawable(value, id);在这个里面我们可以看到关键代码 

 Drawable dr = getCachedDrawable(isColorDrawable ? mColorDrawableCache : mDrawableCache, key);

        if (dr != null) {
            return dr;
        }
在此可以看出,如果缓存Drawable不为空,那么就返回原先使用的Drawable,在我们这里,这个Drawable引用的Bitmap已经被recycle了,但是Drawable这个缓存对象是一直并引用那个失效的Bitmap。其实系统这样设计我们可以理解,为了不用再次加载这个Bitmap为了节省系统资源,但在我们此处因为要使用到大量图片来播放动画(也有别的需求只是加载大图片,防止内存溢出,所以退出页面时recycle这个图片),所以系统的这种方法对我们来说是会适得其反的。

找到问题的要点,那么我们着手开始解决这个问题

1、在退出页面执行onDestory()回调的时候,回收图片资源以及把AnimationDrawable的对象置空,并调用GC让系统尽快回收

@Override
	protected void onDestroy() {
		super.onDestroy();

		
		//资源回收否则会造成内存溢出
		tryRecycleAnimationDrawable(animation);
		AnimationDrawble置空
		animation = null;
		把针对AnimationDrawble的引用置空
		tv.setBackground(null);
		系统垃圾回收
		System.gc();
	}
	//把AnimationDrawable中的图片资源逐个回收
	private void tryRecycleAnimationDrawable(
			AnimationDrawable animationDrawables) {
		if (animationDrawables != null) {
			animationDrawables.stop();
			for (int i = 0; i < animationDrawables.getNumberOfFrames(); i++) {
				Drawable frame = animationDrawables.getFrame(i);
				if (frame instanceof BitmapDrawable) {
					Bitmap bitmap = ((BitmapDrawable) frame).getBitmap();
					bitmap.recycle();
					bitmap = null;
				}
				frame.setCallback(null);
			}

			animationDrawables.setCallback(null);

		}
	}
2、重点在再次进入程序后如果不再调用cacheDrawable

很遗憾的是我们默认的加载系统资源的方法getResource(context).getDrawable(id)默认会调用该方法来加载资源 ,我们只能另辟捷径了。使用系统最原始方法加载图片资源 BitmapFactory.decodeResource(res, resId);










上一篇:angularjs官方教程 -
下一篇:【《Effective C#》提炼总结】提高Unity中C#代码质量的21条准则

相关文章

相关评论

本站评论功能暂时取消,后续此功能例行通知。

一、不得利用本站危害国家安全、泄露国家秘密,不得侵犯国家社会集体的和公民的合法权益,不得利用本站制作、复制和传播不法有害信息!

二、互相尊重,对自己的言论和行为负责。

好贷网好贷款