Bitmap进化史及不同版本下的回收

在App开发中,如果对Bitmap的管理不是很谨慎,就很容易出现OOM。虽然现在网上有许多优秀的开源图片加载框架,但在有些情况无法使用那些框架去加载图片,比如比较 复杂的自定义View。本文结合GOOGLE的一篇文章(原文地址)对不同版本Bitmap的变化以及如何更好地回收掉做下介绍,如果有不对的地方,欢迎指正。


Android管理Bitmap内存进化史

在Android2.2(API8)及更早版本,当GC(Garbage collection)触发,你的app线程停止,这将导致可以降低性能的滞后

在Android2.3(API9)添加并发GC,也就是说,当一个bitmap对象不再被引用,gc将尽快的回收掉bitmap使用的内存

在Android2.3.3(API10)及更早版本,一个bitmap对象所包含的像素数据是存在本地内存(native memory,也就是 Dalvikheap)当中,也就是说像素数据与bitmap本身是分离开来的,而在native memory中的像素数据不会按预期的方式释放掉,这也就有可能导致程序超过内存的限制并OOM

在Android3.0(Api11)及之后版本,像素数据与关联的bitmap都保存在Dalvik heap中


在不同版本管理Bitmap 内存

在Android2.3.3(API10)及之前版本,google推荐使用recycle()方法来释放内存,recycle()会尽快的去释放掉bitmap使用的内存,注意,如果你确定不再使用这个bitmap的时候再调用recycle()方法,如果调用以后再次使用这个bitmap,将会产生错误"Canvas:trying to use a recycled bitmap"

在Android3.0(API11)及之后版本,android引入了BitmapFactory.Options.inBitmap属性,如果设置了这个属性,使用decode方法去获取bitmap时,android将会尝试重用一个已经存在的bitmap并替换像素数据,也就是说bitmap的内存被重用了,这样做的好处是省去了申请内存以及将之前申请的内存释放掉的过程,也就提升了应用的性能。但是,使用inBitmap有严格的限制,在android4.4(API19)之前,只有同样大小的bitmap才支持此属性,就是说,如果已经存在一个不需要的bitmap大小为400*400,而你此时要加载一个400*400的bitmap,则可以将新的bitmap的像素数据填充到之前的bitmap中,这样不必再释放之前的bitmap内存,然后再为新的bitmap重新申请内存,但是如果新要加载的bitmap大小与之前的bitmap尺寸不一,则无法复用。如果decode无法使用这个bitmap,decode方法将会返回null并抛出IllegalArgumentException,感觉还是挺麻烦的,具体使用可以参考官方API。



你可能感兴趣的:(Android,Bitmap,内存,oom)