天天看点

Android中内存优化之(Bitmap1)

Android应用开发中经常会遇到的问题:

1. 解码Bitmap的时候产生OutOfMemory错误

2. 主动回收Bitmap的时候,因为回收时机把握不到位产生的tring to use a recycled bitmap异常

3. ListView,GridView中因为要加载很多Bitmap,因为放在UI线程里decode导致主线程顿卡

4. 自己写图片浏览器时要加载高清大图,有可能因为内存紧张问题连一张图片原始大小的Bitmap都解码不出来

解决问题的思路:

  • 单个或少数大图片处理(场景:图片浏览器 )

1. 增大缩放系数,用 BitmapFactory.Options       

2. 图片源文件进行转换,一些没有透明的PNG图片完全可以转化为JPG格式,这样内存至少节省25%。当然在生成JPG的时候,Config选择RGB565效果更明显

3. 局部解码,Android2.3.3开始加入一个BitmapRegionDecoder的类,可以实现局部解码。当然这个做图片浏览控件需要的计算稍微麻烦,不过好在Github上有人已经做好了,直接拿来主义吧。开源项目的地址:https://github.com/diegocarloslima/ByakuGallery

4. 当然如果你非要支持2.3.3一下的,又要求不失真。那要么自己研究JPG,PNG的解码,自己写算法。当然,现成的算法其实就在AOSP里面,下载Android系统的源码,自己编译,这需要C,C++,JNI等NDK相关的开发知识。最近忙,如果有空的话我会试试,弄好了当然是发上来了。

  • ListView或GridView的优化

1.View复用就不多说了。

2.Bitmap的decode放在异步线程里处理,可以用AsyncTask,也可以自己写线程。Bitmap被解码出来后,要监测Bitmap对应位置的View是否可见,如果可见的话刷新对应的View。关于Bitmap的优化处理,Android官方有不错的解决方法http://developer.android.com/training/building-graphics.html。

3.时刻监控当前APP虚拟机的内存状况,超出罚值就回收部分不可见的bitmap。例如当已使用内存大于最大内存的一半 Runtime.getRuntime().totalMemory()-Runtime.getRuntime().freeMemory()>Runtime.getRuntime().totalMemory()/2

4.人工干预GC。bitmap.recycle()在你需要及时清除缓存的时候还是很有必要调用的,否则ListView加载很多图片时内存会很快飙升的。如果不调用很可能虚拟机会抛出OOM的错误。因此,建议在ListView,GridView加载大量图片的时候,还是要人工调用bitmap.recycle()方法,必要的时候调用System.gc()以加快内存的释放

5.关于tring to use a recycled bitmap问题的解决。如果是在onDestroy()的时候,去把所有的Bitmap回收掉可能会产生这样的错误。我们可以通过延时个1秒2秒的再去回收,当然这对于很多程序员来说是难以接受的,到底延时多少呢。其实,我们可以先设置相关的ImageView的可见性为不可见,然后再回收即可。还有就是刷新ListView数据的时候,老的数据不用了,对应的BItmap调用了recycle方法,可能会导致出现这样的错误,解决的办法是等等再处理这些BItmap,找到合适的时机,比如新的数据已经加载好了,或者内存不够用的时候顺便把这部分垃圾回收掉即可