曾经我们使用 WeakReference 来处理 Android 中 Out of Memory 的问题。但是随着 Google 修改了回收机制的行为,这个方法已经没什么用了。

因此,Google 为我们提供了一个新的数据结构,LRU cache。

它的使用是这样的

LruCache bitmapCache = new LruCache<String, Bitmap>()

像是使用 Map ,但是它有一些独特的行为特性。

使用前,我们需要确定 cache 的大小。如何确定需要多大的空间? Google 给了我们一个最佳实践的空间计算方法。g

ActivityManager am = (ActivityManager)
        getSystemService(Context.ACTIVITY_SERVICE);
int availMemInBytes = am.getMemoryClass() * 1024 * 1024;
LruCache bitmapCache = 
        new LruCache<String, Bitmap>(availMemInBytes / 8);

另外还有一个重要的部分是我们需要告诉 cache 每个 bitmap 的大小,如何告诉?重写 sizeOf 方法

public class ThumbnailCache extends LruCache(String, Bitmap) {
    
    @Override
    protected int sizeOf(String key, Bitmap value) {
        return value.getByteCount();
    }
}

前面提到过使用 cache 像是使用 Map。但是这个 cache 可能会返回 null,表示 cache 中找不到我们需要的文件,这时候我们就需要从其他地方载入图片然后把它塞进 cache 中。

Bitmap bmpToDraw = mCache.get(filename);
if(bmpToDraw == null) {
    bmpToDraw = BitmapFactory.decodeFile(filename);
    mCache.put(filename, bmpToDraw);
}

当我们塞进一张图片进 cache 中时, cache 中的其他图片可能会被删除。Lru Cache 删除图片的策略就是最不常用的图片会被删除。