12.1.4 图像的管理
在实际开发中,开发者常需要处理各种特征的图像。把图像放在内存中会带来很大的开销,导致内存溢出,把图像从文件中读取出来又会有不小的时间开销,如何在内存开销和时间效率上求得平衡,就是开发中图像管理的最重要课题。
如果在开发中需要处理大量小图片(比如:图标、头像、缩略图等),那么将图片对象“池化”进行管理就是不错的思路。Android系统的联系人应用提供了一个很好的内存池实现范例。
在Android的联系人应用中,使用android.util.LruCache[1]对象来存储联系人的头像信息:
int cacheSize=1024*1024;//最多使用1兆空间
mBitmapCache=new LruCache<Object, Bitmap>(cacheSize){
protected int sizeOf(String key, Bitmap value){
//返回每张图片占用的内存空间,使得可以计算总空间
return value.getByteCount();
}
}
…
//在使用时,不断调用其中图像,或者进行更新
Bitmap bitmap=mBitmapCache(key);
if(bitmap==null){
…
mBitmapCache.put(key, newBitmap);
}
LruCache是基于最近最少使用(Least Recently Used, LRU)算法,保存最近常使用的图像对象,淘汰不常使用的对象。每个LruCache会被设置一个阈值,所有对象按照最近访问频率排序,超出阈值后,最近不被使用的就自动释放了。
Android的联系人应用,会把这些图像缓存放在应用环境对象中,使得缓存信息在每个应用进程中是唯一的:
//联系人的应用环境对象(真实的实现要更为复杂,这里做了简化)
public final class ContactsApplication extends Application{
private LruCache mBitmapCache;
…
@Override
public void onTrimMemory(int level){
//当内存过低时,释放缓存的图像信息
mBitmapCache.evictAll();
…
}
}
通过重载Application.onTrimMemory函数[2],可以在Android系统内存紧张时,释放掉所有缓存的图像对象,以保证系统和应用可以更为流畅地运行。
[1]LruCache对象,是从Android 3.1(SDK 12)开始支持的,对于低版本的Android应用,可以参照LruCache的实现。基于LRU算法提供类似的实现,文档地址在:http://developer.android.com/reference/android/util/LruCache.html。
[2]Application.onTrimMemory函数是从Android 4.0(SDK 14)开始支持的,通过该函数,可以更精准地获知Android设备上内存状况;而在低版本的Android中,可以通过重载Application.onLowMemory函数获得类似的实现效果。