从网络上加载一张图,然后把它显示到UI上是个很简单的事情。当图片变多时,处理起来就有些麻烦了,很典型的应用场景,如ListView,GridView或者ViePager等。我们既需要保证用户看到更多的图片,以免屏幕出现大面积的空白,又要保证内存能Hold住。
GC会自动释放一个没有强引用的图片或者View,这本来是个好事情,但为了让用户来回滚动时还能快速加载老图片,通常会使用图片缓存。这篇文章就分享一下使用memory cache和disk cache来增加UI的响应速度和流畅度。一、使用memory cache
memory cache花费定量的内存来换取对图片的快速访问。可以使用Support Library中的LruCache来快速实现。过去,我们通常使用SoftReference或WeakReference来实现memory cache,但是在Android 2.3 (API Level 9)之后,GC对SoftReference和WeakReference回收的更快,所以,SoftReference和WeakReference的效果就很差了。而且,在Android 3.0 (API Level 11)之前,Bitmap的像素数据存放在Native Memory中,如何释放是不确定的,存在着内存泄漏,甚至Crash的风险。
为了确定LruCache的大小,我们需要参考如下几个因素:
1、当前进程的剩余内存有多少
2、为了保证良好的用户体验,应用场景显示多少张图片可以满足要求?
3、屏幕的density是多少?不同像素的屏幕对图片质量的要求是不一样的,可以据此在取图时做一些优化。
4、图片被访问的频率是否相差很多?如果是这样的话可以存放在不同的LruCache中。
5、有时需要在数量和质量之间做一些平衡。比如为图片列表在memory cache中缓存较多的缩略图,在UI中先显示缩略图,然后在后台加载一张高清的。
这里没有一个精确的数字来做为指导,需要我们在实际中就以上几个因素进行权衡,设置合适的值。至于如何使用LruCache可以参考Support Library中的Demo。
二、使用Disk Cache
memory cache可以加快图片的访问速度,但内存有限,不可能所有图片都放在memory cache中。当程序先被挤出内存,后又被重新启动时,图片仍需要重新获取。这个时候,可以应用Disk Cache来缓存图片,图片就不需要从网络上获取了,节省了流量,减少了获取时间。但需要注意,Disk Cache的读取涉及到本地IO操作,需要开启后台线程操作。
我们可以像系统Gallery那样使用ContentProvider。另外,Disk Cache也可以很简单地通过Android源码中提供的DiskLruCache来实现。
本文翻译自:http://developer.android.com/training/displaying-bitmaps/cache-bitmap.html