如果每次加载同一张图片都要从网络获取,那代价实在太大了。所以同一张图片只要从网络获取一次就够了,然后在本地缓存起来,之后加载同一张图片时就从缓存中加载就可以了。从内存缓存读取图片是最快的,但是因为内存容量有限,所以最好再加上文件缓存。文件缓存空间也不是无限大的,容量越大读取效率越低,因此可以设置一个限定大小比如10M,或者限定保存时间比如一天。
因此,加载图片的流程应该是:
-
先从内存缓存中获取,取到则返回,取不到则进行下一步;
-
从文件缓存中获取,取到则返回并更新到内存缓存,取不到则进行下一步;
-
从网络下载图片,并更新到内存缓存和文件缓存。
接下来看内存缓存类:ImageMemoryCache
public class ImageMemoryCache { /** * 从内存读取数据速度是最快的,为了更大限度使用内存,这里使用了两层缓存。 * 硬引用缓存不会轻易被回收,用来保存常用数据,不常用的转入软引用缓存。 */ private static final int SOFT_CACHE_SIZE = 15; //软引用缓存容量 private static LruCachemLruCache; //硬引用缓存 private static LinkedHashMap > mSoftCache; //软引用缓存 public ImageMemoryCache(Context context) { int memClass = ((ActivityManager)context.getSystemService(Context.ACTIVITY_SERVICE)).getMemoryClass(); int cacheSize = 1024 * 1024 * memClass / 4; //硬引用缓存容量,为系统可用内存的1/4 mLruCache = new LruCache (cacheSize) { @Override protected int sizeOf(String key, Bitmap value) { if (value != null) return value.getRowBytes() * value.getHeight(); else return 0; } @Override protected void entryRemoved(boolean evicted, String key, Bitmap oldValue, Bitmap newValue) { if (oldValue != null) // 硬引用缓存容量满的时候,会根据LRU算法把最近没有被使用的图片转入此软引用缓存 mSoftCache.put(key, new SoftReference (oldValue)); } }; mSoftCache = new LinkedHashMap >(SOFT_CACHE_SIZE, 0.75f, true) { private static final long serialVersionUID = 6040103833179403725L; @Override protected boolean removeEldestEntry(Entry > eldest) { if (size() > SOFT_CACHE_SIZE){ return true; } return false; } }; } /** * 从缓存中获取图片 */ public Bitmap getBitmapFromCache(String url) { Bitmap bitmap; //先从硬引用缓存中获取 synchronized (mLruCache) { bitmap = mLruCache.get(url); if