这些类的继承关系例如以下图所看到的:
如同文件缓存一样,内存缓存涉及的接口也有两个:MemoryCacheAware 和MemoryCache,当中MemoryCache仅仅是简单的继承了MemoryCacheAware并没有声明其它的方法。
MemoryCacheAware接口的方法例如以下:
@Deprecated public interface MemoryCacheAware<K, V> { /** *依据key值把value放入缓存 * @return 假设放入缓存成功的话就返回true,反之返回false */ boolean put(K key, V value); /**依据key从缓存中获取数据,没有相关数据则返回null*/ V get(K key); /** 依据key从缓存中删除数据*/ void remove(K key); /** 返回缓存中全部的key */ Collection<K> keys(); /** 清空缓存*/ void clear(); }
以下具体介绍这些缓存的作用以及实现方式,先从BaseMemoryCache以及其子类開始
BaseMemoryCache:
该类是一个抽象类,提供了一个map,用来缓存Bitmap的弱引用:
private final Map<String, Reference<Bitmap>> softMap = Collections.synchronizedMap(new HashMap<String, Reference<Bitmap>>());
当中softMap的value字段就是保存了Bimmap的引用类型,因为Reference又分为强引用。弱引用,软引用以及虚引用。所以该该类另外还提供了一个抽象方法createReference(Bitmap value)让子类重写,依据不同的要求来返回不同的应用类型。该抽象方法是将Bitmap转换成一个Reference。在调用BaseMemoryCache的put方法时调用。
/**依据value创建一个弱引用对象。该类为抽象类。供子类实现 */ protected abstract Reference<Bitmap> createReference(Bitmap value); @Override public boolean put(String key, Bitmap value) { softMap.put(key, createReference(value)); return true; }
LimitedMemoryCache:
该类为抽象类。继承了BaseMemoryChache。对缓存进行了两个限制:1) 限制每个缓存图片的最大值:用sizeLimit来作为标致,对大于sizeLimit大小的bitmap对象。调用父类的put方法保存bitmap的弱引用。
否则在保存弱引用的同一时候,把Bitmap对象的强引用用类型为LinkedList变量hardCache缓存起来,
2) 相同用sizeLimit来限制整个缓存的大小。对是否超出缓存大小的限制在put方法被调用的时候会做推断。假设缓存大小超出限制就从LinkedList中删除相应的bitmap对象,详细的删除策略有该类的抽象方法remoeNext()提供。详细的在子父类中实现(比方有的是删除最大的那个bitMap,以及依据FIFO算法删除等等),这是典型的模板方法模式的应用。详细的模板方法为romoveNext()和getSize()由相应的子类实现。
注意put方法的返回值,当要增加的bitMap的大小超过sizeLimit的就返回false。否则返回true(在子类中调用该put方法。返回true说明对缓存进行了相应的删除操作)
private final List<Bitmap> hardCache = Collections.synchronizedList(new LinkedList<Bitmap>());<span style="color:#0000C0;">//hardCache</span><span style="color:#0000C0;">仅仅是在此类中仅仅是用来对缓存是否超过</span><span style="color:#0000C0;">sizeLimit</span><span style="color:#0000C0;">做推断。</span> //bitMap放入缓存 @Override public boolean put(String key, Bitmap value) { boolean putSuccessfully = false; // Try to add value to hard cache //getSize方法为抽象方法,由子类实现 int valueSize = getSize(value); int sizeLimit = this.sizeLimit; int curCacheSize = cacheSize.get(); //当bitmap的大小小于sizeLimit的大小时 if (valueSize < sizeLimit) { //对缓存进行删除操作,使之不超过siezeLimit的限制,。我们 while (curCacheSize + valueSize > sizeLimit) { Bitmap removedValue = removeNext();//removeNext()为抽象方法,由不同的子类提供不同的删除策略 if (hardCache.remove(removedValue)) { curCacheSize = cacheSize.addAndGet(-getSize(removedValue)); } } //放入缓存 hardCache.add(value); //设置缓存大小 cacheSize.addAndGet(valueSize); putSuccessfully = true; } //获取bitMap的大小 protected abstract int getSize(Bitmap value); //模板方法,由对应的子类来实现详细的删除策略 protected abstract Bitmap removeNext();
LargesetLimitedMemoryCache:
该类为LimitedMemoryCache的子类,该类的目的是当超出缓存限制大小的时候删除缓存中最大的那个bitmap对象。
该类实现了父类的两个抽象方法:getSize()和removeNext()来获取某个bitmap的大小和删除最大的那个bitMap对象。
实现的原理: 该类加入了一个map变量,该map的key用来保存bitMap对象,而相应的value则保存bitmap的大小。
private final Map<Bitmap, Integer> valueSizes = Collections.synchronizedMap(new HashMap<Bitmap, Integer>());
详细的removeNext()实现:
/** * 循环遍历valueSizes,并获取最大的那个bitmap,而且从map中删除之 返回的Bimmap对象交给父类的hardCache删除 */ @Override protected Bitmap removeNext() { Integer maxSize = null; Bitmap largestValue = null; Set<Entry<Bitmap, Integer>> entries = valueSizes.entrySet(); synchronized (valueSizes) { for (Entry<Bitmap, Integer> entry : entries) { if (largestValue == null) { largestValue = entry.getKey(); maxSize = entry.getValue(); } else { Integer size = entry.getValue(); if (size > maxSize) { maxSize = size; largestValue = entry.getKey(); } } } } //运行删除稻作 valueSizes.remove(largestValue); return largestValue; } //获取getSize的方法 @Override protected int getSize(Bitmap value) { return value.getRowBytes() * value.getHeight(); } @Override protected Reference<Bitmap> createReference(Bitmap value) { return new WeakReference<Bitmap>(value); }
删除操作运行时机:调用父类put方法是运行
<span style="font-size:12px;">@Override public boolean put(String key, Bitmap value) { if (super.put(key, value)) {//假设父类的方法为空。说明缓存的大小没有超出限制 valueSizes.put(value, getSize(value)); return true; } else {//缓存的大小超出限制 return false; } }</span>
FIFOLimitedMemoryCache :
LimitedMomroyCache的子类,当当前缓存的大小超出限制的时候,会依据FIFO(先进先出)算法删除响应的bitmap缓存对象。该类用LinkedList来作为FIFO的实现方式,当超出缓存大小的时候,调用removeNext()来从缓存中删除首先增加进来的bitmap对象。对应的方法例如以下:
实现原理:提供了一个LinkedList来保存bitmap对象
private final List<Bitmap> queue = Collections.synchronizedList(new LinkedList<Bitmap>());
详细的removeNext()方法实现:
@Override protected Bitmap removeNext() { return queue.remove(0); } @Override protected Reference<Bitmap> createReference(Bitmap value) { return new WeakReference<Bitmap>(value); } @Override protected int getSize(Bitmap value) { return value.getRowBytes() * value.getHeight(); }删除操作运行时机:调用父类put方法是运行
@Override public boolean put(String key, Bitmap value) { if (super.put(key, value)) {//假设缓存没有超出范围 queue.add(value);//把bitmap放入队列 return true; } else {//缓存超出范围 return false; } }
LRULimitedMemoryCache:
LimitedMemoryCache的子类。近期最久未使用缓存,当缓存大小超过sizeLimit限制的时候。就从缓存中删除近期最久未使用的bitmap缓存对象。实现原理:提供了一个LinkedHashMap来保存对象,实现LRU的效果
/** Cache providing Least-Recently-Used logic */ private final Map<String, Bitmap> lruCache = Collections.synchronizedMap(new LinkedHashMap<String, Bitmap>(INITIAL_CAPACITY, LOAD_FACTOR, true));详细的removeNext()方法实现:
@Override protected Bitmap removeNext() { return queue.remove(0); } @Override protected Reference<Bitmap> createReference(Bitmap value) { return new WeakReference<Bitmap>(value); } @Override protected int getSize(Bitmap value) { return value.getRowBytes() * value.getHeight(); }
删除操作运行时机:调用父类put方法是运行
@Override public boolean put(String key, Bitmap value) { if (super.put(key, value)) {//假设缓存没有超出范围 queue.add(value);//把bitmap放入队列 return true; } else {//缓存超出范围 return false; } }
UsingFreqLimitedMemoryCache:
LimitedMemoryCache的子类,当缓存大小超出sizelimit的时候对最久未使用的bitmap对象进行删除(也就是说对使用次数最少的那个bitmap进行删除操作)
实现原理:提供了一个hashMap。该map的key保存bitmap对象,而value则保存相应bitmap的使用次数
private final Map<Bitmap, Integer> usingCounts = Collections.synchronizedMap(new HashMap<Bitmap, Integer>());当调用get(string key)方法获取bitmap的时候,该bitmap的使用次数进行+1操作
@Override public Bitmap get(String key) { Bitmap value = super.get(key); // Increment usage count for value if value is contained in hardCahe if (value != null) { Integer usageCount = usingCounts.get(value); if (usageCount != null) { //使用次数+1 usingCounts.put(value, usageCount + 1); } } return value; }
详细的removeNext()实现方法:
@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) { 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); }
删除操作运行时机:调用父类put方法是运行
@Override public boolean put(String key, Bitmap value) { if (super.put(key, value)) { usingCounts.put(value, 0); return true; } else { return false; } }
LimitedAgeMemoryCache:
对超出时间限制的缓存对象进行删除,该类的实现毕竟简单。详细代码例如以下:public class LimitedAgeMemoryCache implements MemoryCache { private final MemoryCache cache; private final long maxAge; private final Map<String, Long> loadingDates = Collections.synchronizedMap(new HashMap<String, Long>()); /** * @param cache Wrapped memory cache * @param maxAge Max object age <b>(in seconds)</b>. If object age will exceed this value then it'll be removed from * cache on next treatment (and therefore be reloaded). */ public LimitedAgeMemoryCache(MemoryCache cache, long maxAge) { this.cache = cache; this.maxAge = maxAge * 1000; // to milliseconds } @Override public boolean put(String key, Bitmap value) { boolean putSuccesfully = cache.put(key, value); if (putSuccesfully) { loadingDates.put(key, System.currentTimeMillis()); } return putSuccesfully; } @Override public Bitmap get(String key) { Long loadingDate = loadingDates.get(key); //推断是否超时 if (loadingDate != null && System.currentTimeMillis() - loadingDate > maxAge) { cache.remove(key); loadingDates.remove(key); } return cache.get(key); } @Override public void remove(String key) { cache.remove(key); loadingDates.remove(key); } @Override public Collection<String> keys() { return cache.keys(); } @Override public void clear() { cache.clear(); loadingDates.clear(); } }
FuzzyKeyMemoryCache:
该缓存的作用就是假设缓存中的有一个key和要增加的keytemp相等。就从缓存中删除该key指向的bitmap对象,然后把新的key对象增加到缓存中去。
详细的逻辑例如以下:
@Override public boolean put(String key, Bitmap value) { // Search equal key and remove this entry synchronized (cache) { String keyToRemove = null; for (String cacheKey : cache.keys()) { //推断缓存中相应的key是否存在,存在就删除 if (keyComparator.compare(key, cacheKey) == 0) { keyToRemove = cacheKey; break; } } if (keyToRemove != null) { cache.remove(keyToRemove); } } return cache.put(key, value); }
LruMemoryCache:
又一个近期最久未使用缓存,在这里就不多说了,直接贴代码:
@Override public final boolean put(String key, Bitmap value) { synchronized (this) { size += sizeOf(key, value); Bitmap previous = map.put(key, value); if (previous != null) { size -= sizeOf(key, previous); } } //缓存瘦身,把近期最久未使用的bitMap删除 trimToSize(maxSize); return true; } private void trimToSize(int maxSize) { while (true) { String key; Bitmap value; synchronized (this) { Map.Entry<String, Bitmap> toEvict = map.entrySet().iterator().next(); if (toEvict == null) { break; } key = toEvict.getKey(); value = toEvict.getValue(); map.remove(key); size -= sizeOf(key, value); } } }