Bitmap recycle()
Bitmap调用recycle? When?
Bitmap有一个recycle方法。含义很easy,恢复Bitmap空间。
Q 1: Bitmap有调用recycle方法的必要性?
A: 嵌入式系统总是格外注重空间的问题,不小心的话就会有OOM。
可是应用层使用java的android平台有其天然的优势【java语言有自己的垃圾回收,android平台上各个application有自己的process自己的空间】。
无需调用bitmap的理由有:
a. 垃圾回收会处理的。
b. 当application关闭,process被杀掉。全部这个process占用的空间自然回归系统;
可是。假设你有点洁癖。或者有点理想主义。或者非常有控制欲,或者非常闲。。。
bitmap的recycle函数的调用还是能够是有必要的,理由有:
a. 垃圾回收尽管好使,可是有可能的话,我们还是让它少干点活吧。
垃圾回收有非常大的未来不确定性,会加重未来未知时间点的loading,若有大量bitmap须要垃圾回收处理,那必定垃圾回收须要做的次数就很多其它也发生地更频繁,小心会造成ANR。
可是,若是自己recycle。就能够可控制地分散处理了这些回收任务了。
b. 若是launcher那样一直执行的application,它的process一直存在,memory问题还是多多注意下比較好。
Q2: When?
A: Timing的问题在这里非常重要。
早了就大事不好了,会有这种Exception:
java.lang.RuntimeException,Canvas: trying to use a recycled bitmap
android.graphics.Bitmap@44ebeee0,Canvas.java,955
So, 如何才干够保证不会早了呢?
关于图片显示。重要的时间点:
step1: 设置进去的时间点。
Step2: 画面画出来的时间点;
最保险最笨的做法,在新的图片设置进去以后再recycle掉老的图片,这样做的坏处在于,在某个时间段,你须要的空间是double的【新旧两套都在】。
假设你不偏向于那么做,又有时间,能够考虑后面一个时间点,除了setImage以及其他代码中显示调用那个bitmap的时候我们会检查bitmap,在acticvity变为visible的时候系统还是会去找之前设置进去的bitmap【即使你的onResume方法里面并没有提到去refresh UI。这件事情它也是会去做的,大概不然它就不知道这次该显示些什么了】。
所以,在UI线程里面,在一个不可能被打断的方法里面。是先设置新的bitmap还是先recycle旧的图片是没有影响的。
譬如说 mBitmap.recycle();
mBitmap = ..... //设置
mImageView.setImage(mBitmap);
这种代码是全然能够的。
后面这种做法,最重要的就是确保:在UI线程【由于设置UI显示仅仅能在UI主线程里】里面一个不可能被打断的方法里面。
这个是为了确保在两者之间UI主线程不可能被打断。不可能刚好从invisible变成visible。
所以,特别小心两种东西:
1. 多线程【个人认为最好不要在其它线程里面调用UI用过的bitmap的recycle方法,多线程之间是非常难保证时间顺序的。临时没有想出一种在background thread里面recycle的合理的方式】。
2. 非及时发生的方法:譬如。发intent啊。发notify啊去通知UI主线程去做UI又一次刷新并不能替代mImageView.setImage(mBitmap);这种句子。全然有可能,你确实发了intent出去了。可是目标activity之中的一个还没有做UI又一次设置【Q: maybe没收到 or 收到但还是等待处理。不确定这两种可能是不是都有可能】,这个时候这个acitivity变成visible了,系统仍然试图找旧的图片。找不到了就会报exception了。
PS: java.lang.RuntimeException,Canvas: trying to use a recycled bitmap android.graphics.Bitmap@44ebeee0,Canvas.java,955 这种exception也许你可能无法看到,默认log这似乎仅能够看到uncaught exception,我第一次看到monkey的events.log里面,如果你知道如何在这方面打开相应的电话log trace你也应该能看到。