View view = findViewById(R.id.page_bg); BitmapDrawable bitmapDrawable = (BitmapDrawable) view.getBackground(); view.setBackgroundResource(0); bitmapDrawable.setCallback(null); Bitmap bitmap = bitmapDrawable.getBitmap(); if(bitmap != null && !bitmap.isRecycled()){ bitmap.recycle(); bitmap = null; } System.gc();
情况1、 你A界面中使用了a.png图片,然后做了跳转,finish了A界面,finish的时候,你使用了一下的代码释放了内存:
View view = findViewById(R.id.page_bg); BitmapDrawable bitmapDrawable = (BitmapDrawable) view.getBackground(); view.setBackgroundResource(0); bitmapDrawable.setCallback(null); Bitmap bitmap = bitmapDrawable.getBitmap(); if(bitmap != null && !bitmap.isRecycled()){ bitmap.recycle(); bitmap = null; } System.gc();
然后再次进入A界面,极有可能出现该问题。
情况2、 你在A界面使用了a.png图片,然后在B界面也使用了a.png, A界面没有finish,B界面使用了finsh,并且使用上面同样的方式释放了内存。然后我们正常情况下,A界面会经历onResume的方式来显示,可是这个时候,我们的a.png在内存中已经释放了,所以就会引发上面的
05-07 07:00:37.991: E/AndroidRuntime(6988): java.lang.RuntimeException: Canvas: trying to use a recycled bitmap android.graphics.Bitmap@417fc280
看着字面很简单,很容易理解,实际中找到问题的所在却不是容易的一件事。
也许,你在这一刻是否已经抓狂了,难道就没办法来释放内存来解决潜在的oom问题?
答案是否。像google这样的大公司,他们提供的api,考虑的潜在问题比我们正常程序员考虑的还要深入N倍。
个人从新阅读了相关的api,得出了一下解决办法来释放内存,解除我们潜在的oom情况
无论你是在xml中布局使用了:
android:background ,
还是在java代码中调用了:
setBackground(background);
setBackgroundDrawable(background)
setBackgroundResource(resid)
的方式去设置了背景图片.
使用的时候,请调用一下对应的方法:
setBackgroundResource和android:background →setBackgroundResource(0);
setBackgroundDrawable(background)→ setBackgroundDrawable(null)
setBackground(background) → setBackground(null)
然后再onDestory中调用System.gc();
以上的代码,我们修改为:
View view = findViewById(R.id.page_bg); view.setBackgroundResource(0); System.gc();
我们在看看我们的logcat的结果:
05-07 07:29:18.941: D/dalvikvm(7598): GC_FOR_ALLOC freed 27K, 65% free 9791K/27452K, paused 43ms, total 58ms 05-07 07:29:18.970: I/dalvikvm-heap(7598): Grow heap (frag case) to 13.203MB for 3686416-byte allocation 05-07 07:29:19.041: D/dalvikvm(7598): GC_FOR_ALLOC freed 83K, 52% free 13308K/27452K, paused 72ms, total 72ms 05-07 07:29:19.140: D/dalvikvm(7598): GC_CONCURRENT freed 以上的界面和我们调用了手动释放的方式是不是一样? 呵呵,反复测试多次,看看还会不会导致java.lang.RuntimeException: Canvas: trying to use a recycled bitmap
实际上,我们的程序不会再出现上面的问题了,并且解决了oom得潜在危机。如此的简单,如此的便捷。
同理:如果我们在程序中,使用了ImageView的话, 我们也可以使用
imageView.setImageResource(0); 这种方式,来释放我们设置的android:src或者bitmap等等。
那么,关于图片的oom可能潜在的问题,我们告一段落,从这次的经历,让我更加的深入的了解java语言的内存回收机制,总结一句话:尽可能的让系统去释放内存,我们只负责标示需要释放的内存。通俗点:我们只是标记需要杀的人,谁来杀,就让杀手看着办。
作者:SpringSky
出处:http://blog.csdn.net/springsky_/article/details/25212419
blog:http://blog.csdn.net/springsky_