Android开源框架Universal-Image-Loader学习三——UsingFreqLimitedMemoryCache源码阅读
Universal-Image-Loader的内存缓存策略
1. 只使用的是强引用缓存
- LruMemoryCache(这个类就是这个开源框架默认的内存缓存类,缓存的是bitmap的强引用)
2.使用强引用和弱引用相结合的缓存有
- UsingFreqLimitedMemoryCache(如果缓存的图片总量超过限定值,先删除使用频率最小的bitmap)
- LRULimitedMemoryCache(这个也是使用的lru算法,和LruMemoryCache不同的是,他缓存的是bitmap的弱引用)
- FIFOLimitedMemoryCache(先进先出的缓存策略,当超过设定值,先删除最先加入缓存的bitmap)
- LargestLimitedMemoryCache(当超过缓存限定值,先删除最大的bitmap对象)
- LimitedAgeMemoryCache(当 bitmap加入缓存中的时间超过我们设定的值,将其删除)
3.只使用弱引用缓存
- WeakMemoryCache(这个类缓存bitmap的总大小没有限制,唯一不足的地方就是不稳定,缓存的图片容易被回收掉)
继承关系:
public class UsingFreqLimitedMemoryCache extends LimitedMemoryCache public abstract class LimitedMemoryCache extends BaseMemoryCache public abstract class BaseMemoryCache implements MemoryCache public interface MemoryCache extends MemoryCacheAware<String, Bitmap> @Deprecated public interface MemoryCacheAware<K, V>
1、先来看MemoryCacheAware:
/* Interface for memory cache*/ @Deprecated public interface MemoryCacheAware<K, V> { /*Puts value into cache by key * @return true - if value was put into cache successfully;false - if value was not put into cache */ boolean put(K key, V value); /** Returns value by key. If there is no value for key then null will be returned. */ V get(K key); /** Removes item by key */ V remove(K key); /** Returns all keys of cache */ Collection<K> keys(); /** Remove all items from cache */ void clear(); }
2、现在一般使用MemoryCache替代MemoryCacheAware:
MemoryCacheAware源码:
public interface MemoryCache extends MemoryCacheAware<String, Bitmap> { }
3、BaseMemoryCache 源码:
/*为memory cache提供一些基本功能;提供object的引用(非强引用)存储*/ public abstract class BaseMemoryCache implements MemoryCache { /** 存储objects的非强引用,Collections.synchronizedMap保证线程安全*/ private final Map<String, Reference<Bitmap>> softMap = Collections.synchronizedMap(new HashMap<String, Reference<Bitmap>>()); @Override public Bitmap get(String key) { Bitmap result = null; Reference<Bitmap> reference = softMap.get(key); if (reference != null) { result = reference.get(); } return result; } @Override public boolean put(String key, Bitmap value) { softMap.put(key, createReference(value)); return true; } @Override public Bitmap remove(String key) { Reference<Bitmap> bmpRef = softMap.remove(key); return bmpRef == null ? null : bmpRef.get(); } @Override public Collection<String> keys() { synchronized (softMap) { return new HashSet<String>(softMap.keySet()); } } @Override public void clear() { softMap.clear(); } /** Creates {@linkplain Reference not strong} reference of value */ protected abstract Reference<Bitmap> createReference(Bitmap value); }
4、LimitedMemoryCache源码:
/** * 限定的Cache.提供Object的存储。所有存储的bitmap的总内存大小不超过限定值 * 注:该cache使用强引用和弱引用来存储Bitmaps; * 强引用——对于限额内的bitmaps * 弱应用——对于其他的Bitmaps */ public abstract class LimitedMemoryCache extends BaseMemoryCache { private static final int MAX_NORMAL_CACHE_SIZE_IN_MB = 16; private static final int MAX_NORMAL_CACHE_SIZE = MAX_NORMAL_CACHE_SIZE_IN_MB * 1024 * 1024; private final int sizeLimit; /*AtomicInteger,一个提供原子操作的Integer的类,使得操作线程安全*/ private final AtomicInteger cacheSize; /** * 包含存储objects的强引用。每个object都添加到最尾端;如果hard cache的大超过了限定值,首端的object将会被删除 *(但它依然存在在softMap中,而且可以随时被GC回收) // 返回一个synchronizes封装的线程安全的List public static <T> List<T> synchronizedList(List<T> list)*/ private final List<Bitmap> hardCache = Collections.synchronizedList(new LinkedList<Bitmap>()); /**构造函数:sizeLimit单位bytes */ public LimitedMemoryCache(int sizeLimit) { this.sizeLimit = sizeLimit; cacheSize = new AtomicInteger(); /**检测避免sizeLimit值设置过大 */ if (sizeLimit > MAX_NORMAL_CACHE_SIZE) { L.w("You set too large memory cache size (more than %1$d Mb)", MAX_NORMAL_CACHE_SIZE_IN_MB); } } /**操作成功返回true,操作失败返回false 先尝试将Bitmap添加至hard cache,再将其添加至soft cache*/ @Override public boolean put(String key, Bitmap value) { boolean putSuccessfully = false; int valueSize = getSize(value); //抽象函数,返回Bitmap的大小值 int sizeLimit = getSizeLimit(); //返回sizeLimit int curCacheSize = cacheSize.get();//返回cacheSize的当前值 /**如果添加的bitmap的size大于sizeLimit,则直接不将其添加至hard cache*/ if (valueSize < sizeLimit) { /**判断新添加的Object的valueSize加上当前cache中已有object的curCacheSize超过限定值,则会删除适当Bitmap*/ while (curCacheSize + valueSize > sizeLimit) { Bitmap removedValue = removeNext(); //abstract函数,返回需要删除的下一个Bitmap if (hardCache.remove(removedValue)) { curCacheSize = cacheSize.addAndGet(-getSize(removedValue)); } } hardCache.add(value); //添加到LinkedList<Bitmap>尾部 cacheSize.addAndGet(valueSize);//即cacheSize+valueSize putSuccessfully = true; } // Add value to soft cache super.put(key, value); return putSuccessfully; } @Override public Bitmap remove(String key) { Bitmap value = super.get(key); if (value != null) { if (hardCache.remove(value)) { cacheSize.addAndGet(-getSize(value)); } } return super.remove(key); } @Override publicvoid clear() { hardCache.clear(); cacheSize.set(0); super.clear(); } protected int getSizeLimit() { return sizeLimit; } protected abstract int getSize(Bitmap value); protected abstract Bitmap removeNext(); }
5、UsingFreqLimitedMemoryCache源码:(关键在于get中更新使用频率)
/** * Limited {@link Bitmap bitmap} cache. Provides {@link Bitmap bitmaps} storing. Size of all stored bitmaps will not to * exceed size limit. When cache reaches limit size then the bitmap which used the least frequently is deleted from * cache(删除最少使用频率的bitmap) * NOTE:使用强引用和弱引用; * 强引用:for limited count of Bitmaps (depends on cache size) * 弱应用:for all other cached Bitmaps */ public class UsingFreqLimitedMemoryCache extends LimitedMemoryCache { /** * Contains strong references to stored objects (keys) and last object usage date (in milliseconds). If hard cache * size will exceed limit then object with the least frequently usage is deleted (but it continue exist at * {@link #softMap} and can be collected by GC at any time) */ private final Map<Bitmap, Integer> usingCounts = Collections.synchronizedMap(new HashMap<Bitmap, Integer>()); public UsingFreqLimitedMemoryCache(int sizeLimit) { super(sizeLimit); } @Override public boolean put(String key, Bitmap value) { if (super.put(key, value)) { usingCounts.put(value, 0); return true; } else { return false; } } @Override public Bitmap get(String key) { Bitmap value = super.get(key); // 如果value存在,则usageCount+ 1; if (value != null) { Integer usageCount = usingCounts.get(value); if (usageCount != null) { // 更新value对应的usageCount的值 usingCounts.put(value, usageCount + 1); } } return value; } @Override public Bitmap remove(String key) { Bitmap value = super.get(key); if (value != null) { usingCounts.remove(value); } return super.remove(key); } @Override public void clear() { usingCounts.clear(); super.clear(); } @Override protected int getSize(Bitmap value) { return value.getRowBytes() * value.getHeight(); } @Override protected Bitmap removeNext() { Integer minUsageCount = null; Bitmap leastUsedValue = null; Set<Entry<Bitmap, Integer>> entries = usingCounts.entrySet(); synchronized (usingCounts) { for (Entry<Bitmap, Integer> entry : entries) { //初始化leastUsedValue if (leastUsedValue == null) { leastUsedValue = entry.getKey(); minUsageCount = entry.getValue(); } else { //简单的比较得到最小值 Integer lastValueUsage = entry.getValue(); if (lastValueUsage < minUsageCount) { minUsageCount = lastValueUsage; leastUsedValue = entry.getKey(); } } } } usingCounts.remove(leastUsedValue); return leastUsedValue; } @Override protected Reference<Bitmap> createReference(Bitmap value) { return new WeakReference<Bitmap>(value); } }
郑重声明:本站内容如果来自互联网及其他传播媒体,其版权均属原媒体及文章作者所有。转载目的在于传递更多信息及用于网络分享,并不代表本站赞同其观点和对其真实性负责,也不构成任何其他建议。