缓存分析:public class ImageMemoryCache { private static final int SOFT_CACHE_SIZE = 15; //软引用缓存容量 private static LruCache<String , Bitmap> mLruCache; //硬引用缓存 private static LinkedHashMap<String, SoftReference<Bitmap>> mSoftCache; //软引用缓存 public ImageMemoryCache(Context context) { int memClass = ((ActivityManager)context.getSystemService(Context.ACTIVITY_SERVICE)).getMemoryClass(); int cacheSize = 1024 * 1024 * memClass / 4; //硬引用缓存容量,为系统可用内存的1/4 //参数:容量,加载因子,顺序访问 mSoftCache = new LinkedHashMap<String, SoftReference<Bitmap>>(SOFT_CACHE_SIZE, 0.75f, true) { private static final long serialVersionUID = 6040103833179403725L; @Override protected boolean removeEldestEntry(Entry<String, SoftReference<Bitmap>> eldest) { if (size() > SOFT_CACHE_SIZE) { return true; } return false; } }; mLruCache=new LruCache<String,Bitmap>(cacheSize){ @Override protected void entryRemoved(boolean evicted, String key, Bitmap oldValue, Bitmap newValue) { if (oldValue != null) // 硬引用缓存容量满的时候,会根据LRU算法把最近没有被使用的图片转入此软引用缓存 mSoftCache.put(key, new SoftReference(oldValue)); } @Override protected int sizeOf(String key, Bitmap value) { if (value != null) return value.getRowBytes() * value.getHeight(); else return 0; } }; } /** * 从缓存中获取图片 */ public Bitmap getBitmapFromCache(String url) { Bitmap bitmap; //先从硬引用缓存中获取 synchronized (mLruCache) { bitmap = mLruCache.get(url); if (bitmap != null) { //如果找到的话,把元素移到LinkedHashMap的最前面,从而保证在LRU算法中是最后被删除 mLruCache.remove(url); mLruCache.put(url, bitmap); return bitmap; } } //如果硬引用缓存中找不到,到软引用缓存中找 synchronized (mSoftCache) { SoftReference<Bitmap> bitmapReference = mSoftCache.get(url); if (bitmapReference != null) { bitmap = bitmapReference.get(); if (bitmap != null) { //将图片移回硬缓存 mLruCache.put(url, bitmap); mSoftCache.remove(url); return bitmap; } else { mSoftCache.remove(url); } } } return null; } /** * 添加图片到缓存 */ public void addBitmapToCache(String url, Bitmap bitmap) { if (bitmap != null) { synchronized (mLruCache) { mLruCache.put(url, bitmap); } } } public void clearCache() { mSoftCache.clear(); } }
- 两级缓存,分为硬缓存,软缓存。
LruCache<String, Bitmap> mLruCache; //硬引用缓存
LruCache 源码中包括了数据结构private final LinkedHashMap<K, V> map; LinkedHashMap是有序的Hashmap
LinkedHashMap<String, SoftReference<Bitmap>> mSoftCache; //软引用缓存 SoftReference是软引用,可能被虚拟机自动回收。
-
存放的时候,按照LRU算法直接存到硬缓存中。查找的时候首先在硬缓存中找,找不到再从软缓存中找,找到都放到硬缓存首部,都没找到就返回null。
SoftReference
SoftReference使用实例:缓存设计,我们希望被缓存的对象最好始终常驻内存,但是如果JVM内存吃紧,为了不发生OutOfMemoryError导致系统崩溃,必要的时候也允许JVM回收Cache的内存,待后续合适的时机再把数据重新Load到Cache中。
在上面的例子中,如果缓存中软引用被回收了,就被判断为空,则键值对也被移出Hashmap。当硬缓存满的时候再加载进去。