Android Bitmap Caching Bitmaps(渣翻译)

三、缓存图像

1.使用内存缓存
内存缓存在提高占用APP内存的情况下,提供快速访问图像的便利。
提倡使用LruCache来引用图像(早在API4的Support Library中已经提供该类),通过强引用LinkedHashMap来缓存LruCache,保持最新最近使用的LruCache,移除最后使用的LruCache,从而避免内存溢出。
在过去的缓存引用方式中,比较流行使用SoftReference或者WeakReference来引用图像,然而,在API 9(Android 2.3)开始,资源回收器加强了对它们的回收力度,从而导致它们相当的无效。

为了创建一个大小合适的LruCache,需要考虑一些因素:
A、你的Activity/APP运行后还剩余多大的可用内存(未达到应用的内存限制)
B、一次性加载多少图片到屏幕上;需要(在内存中)准备多少可用的图片来加载到屏幕上,让屏幕上先显示一部分加载好的图片,再继续加载其他未加载的图片,让用户有事可干而不是漫长的等待
C、屏幕的大小和设备的显示密度;加载相同数量的图像到缓存中,高显示密度的设备 xhdpi(如Galaxy Nexus)比低一点的显示密度的设备hdpi(如Galaxy Nexus S)消耗的内存多
D、加载到内存的图像是什么尺寸和配置以及每张图像占多少内存
E、缓存图像的访问频率;哪些图像访问频率要高于其他的,对于访问频率高的图像,可能需要将它们更优先缓存在内存中,或者创建多重LruCache
D、平衡质量与数量;有时候,缓存大量的低质量图像的方式比开启一个线程去加载一个高质量图像要好的多

基本上没有一个特定的大小或准则来使用所有的应用,这只能取决于你对使用状况的分析以及构思出一个合适的解决方案。毕竟,加载一个太小的无用缓存只会造成浪费,而太大可能会导致java.lang.OutOfMemory
异常或APP可用内存偏低(未达到应用的内存限制)

首先需要获取VM可用的最大内存值(Mb),超过这个值会触发OutOfMemory异常,需要注意的是,存储在LruCache中的图像是以Kb计算的,在计算存储大小的时候记得单位转换

final int maxMemory = (int)(Runtime.getRuntime().maxMemery() / 1024);
//假设去1/8的maxMemory来缓存图像
final int cacheSize = maxMemory / 8;
LruCache<String, Bitmap> mMemoryCache = new LruCache<String, Bitmap>(cacheSize) {
    @Override
    protected int sizeOf(String key, Bitmap bitmap) {
        // The cache size will be measured in kilobytes rather than
        // number of items.
        return bitmap.getByteCount() / 1024;
    }
};
//缓存图像
if (mMemoryCache.get(key) == null) {
    mMemoryCache.put(key, bitmap);
}

2.使用本地缓存
内存缓存在快速访问最近显示过的图像是很有用,然而你不能过分依赖这些加载过在内存里的图像。像GridView这类组件,当加载大量数据的时候很容易就填满内存缓存。
你的应用会因一个其他的任务(如来电电话)的拦截而被置于后台,你的应用可能会被kill并且缓存被回收掉(系统杀人劫货啦)。当你的应用再从onResume()方法中恢复时,
应用不得不再次去加载每一个图像。