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函数获得类似的实现效果。