Android-Universal-Image-Loader学习笔记(3)--内存缓存
這些類的繼承關系例如以下圖所看到的:
如同文件緩存一樣,內存緩存涉及的接口也有兩個:MemoryCacheAware 和MemoryCache,當中MemoryCache僅僅是簡單的繼承了MemoryCacheAware并沒有聲明其它的方法。
MemoryCacheAware接口的方法例如以下:
@Deprecated public interface MemoryCacheAware<K, V> {/***依據(jù)key值把value放入緩存* @return 假設放入緩存成功的話就返回true,反之返回false*/boolean put(K key, V value);/**依據(jù)key從緩存中獲取數(shù)據(jù),沒有相關數(shù)據(jù)則返回null*/V get(K key);/** 依據(jù)key從緩存中刪除數(shù)據(jù)*/void remove(K key);/** 返回緩存中全部的key */Collection<K> keys();/** 清空緩存*/void clear(); }以下具體介紹這些緩存的作用以及實現(xiàn)方式,先從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)讓子類重寫,依據(jù)不同的要求來返回不同的應用類型。該抽象方法是將Bitmap轉換成一個Reference。在調用BaseMemoryCache的put方法時調用。 /**依據(jù)value創(chuàng)建一個弱引用對象。該類為抽象類。供子類實現(xiàn) */protected abstract Reference<Bitmap> createReference(Bitmap value);@Overridepublic 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()提供。詳細的在子父類中實現(xiàn)(比方有的是刪除最大的那個bitMap,以及依據(jù)FIFO算法刪除等等),這是典型的模板方法模式的應用。詳細的模板方法為romoveNext()和getSize()由相應的子類實現(xiàn)。
注意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放入緩存@Overridepublic boolean put(String key, Bitmap value) {boolean putSuccessfully = false;// Try to add value to hard cache//getSize方法為抽象方法,由子類實現(xiàn)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);//模板方法,由對應的子類來實現(xiàn)詳細的刪除策略protected abstract Bitmap removeNext();LargesetLimitedMemoryCache:
??? 該類為LimitedMemoryCache的子類,該類的目的是當超出緩存限制大小的時候刪除緩存中最大的那個bitmap對象。
該類實現(xiàn)了父類的兩個抽象方法:getSize()和removeNext()來獲取某個bitmap的大小和刪除最大的那個bitMap對象。
? 實現(xiàn)的原理: 該類加入了一個map變量,該map的key用來保存bitMap對象,而相應的value則保存bitmap的大小。
private final Map<Bitmap, Integer> valueSizes = Collections.synchronizedMap(new HashMap<Bitmap, Integer>());? 詳細的removeNext()實現(xiàn):
?
/*** 循環(huán)遍歷valueSizes,并獲取最大的那個bitmap,而且從map中刪除之 返回的Bimmap對象交給父類的hardCache刪除*/@Overrideprotected 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的方法@Overrideprotected int getSize(Bitmap value) {return value.getRowBytes() * value.getHeight();}@Overrideprotected Reference<Bitmap> createReference(Bitmap value) {return new WeakReference<Bitmap>(value);}刪除操作運行時機:調用父類put方法是運行
<span style="font-size:12px;">@Overridepublic boolean put(String key, Bitmap value) {if (super.put(key, value)) {//假設父類的方法為空。說明緩存的大小沒有超出限制valueSizes.put(value, getSize(value));return true;} else {//緩存的大小超出限制return false;}}</span>
FIFOLimitedMemoryCache :
LimitedMomroyCache的子類,當當前緩存的大小超出限制的時候,會依據(jù)FIFO(先進先出)算法刪除響應的bitmap緩存對象。該類用LinkedList來作為FIFO的實現(xiàn)方式,當超出緩存大小的時候,調用removeNext()來從緩存中刪除首先增加進來的bitmap對象。對應的方法例如以下:
實現(xiàn)原理:提供了一個LinkedList來保存bitmap對象
private final List<Bitmap> queue = Collections.synchronizedList(new LinkedList<Bitmap>());詳細的removeNext()方法實現(xiàn): @Overrideprotected Bitmap removeNext() {return queue.remove(0);}@Overrideprotected Reference<Bitmap> createReference(Bitmap value) {return new WeakReference<Bitmap>(value);}@Overrideprotected int getSize(Bitmap value) {return value.getRowBytes() * value.getHeight();}刪除操作運行時機:調用父類put方法是運行 @Overridepublic boolean put(String key, Bitmap value) {if (super.put(key, value)) {//假設緩存沒有超出范圍queue.add(value);//把bitmap放入隊列return true;} else {//緩存超出范圍return false;}}
? LRULimitedMemoryCache:
LimitedMemoryCache的子類。近期最久未使用緩存,當緩存大小超過sizeLimit限制的時候。就從緩存中刪除近期最久未使用的bitmap緩存對象。實現(xiàn)原理:提供了一個LinkedHashMap來保存對象,實現(xiàn)LRU的效果
刪除操作運行時機:調用父類put方法是運行 @Overridepublic boolean put(String key, Bitmap value) {if (super.put(key, value)) {//假設緩存沒有超出范圍queue.add(value);//把bitmap放入隊列return true;} else {//緩存超出范圍return false;}}
?UsingFreqLimitedMemoryCache:
LimitedMemoryCache的子類,當緩存大小超出sizelimit的時候對最久未使用的bitmap對象進行刪除(也就是說對使用次數(shù)最少的那個bitmap進行刪除操作)
實現(xiàn)原理:提供了一個hashMap。該map的key保存bitmap對象,而value則保存相應bitmap的使用次數(shù)
private final Map<Bitmap, Integer> usingCounts = Collections.synchronizedMap(new HashMap<Bitmap, Integer>());當調用get(string key)方法獲取bitmap的時候,該bitmap的使用次數(shù)進行+1操作 @Overridepublic Bitmap get(String key) {Bitmap value = super.get(key);// Increment usage count for value if value is contained in hardCaheif (value != null) {Integer usageCount = usingCounts.get(value);if (usageCount != null) {//使用次數(shù)+1usingCounts.put(value, usageCount + 1);}}return value;}詳細的removeNext()實現(xiàn)方法: @Overrideprotected int getSize(Bitmap value) {return value.getRowBytes() * value.getHeight();}@Overrideprotected 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;}@Overrideprotected Reference<Bitmap> createReference(Bitmap value) {return new WeakReference<Bitmap>(value);}
刪除操作運行時機:調用父類put方法是運行
@Overridepublic boolean put(String key, Bitmap value) {if (super.put(key, value)) {usingCounts.put(value, 0);return true;} else {return false;}}
?LimitedAgeMemoryCache:
對超出時間限制的緩存對象進行刪除,該類的實現(xiàn)畢竟簡單。詳細代碼例如以下: 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}@Overridepublic boolean put(String key, Bitmap value) {boolean putSuccesfully = cache.put(key, value);if (putSuccesfully) {loadingDates.put(key, System.currentTimeMillis());}return putSuccesfully;}@Overridepublic 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);}@Overridepublic void remove(String key) {cache.remove(key);loadingDates.remove(key);}@Overridepublic Collection<String> keys() {return cache.keys();}@Overridepublic void clear() {cache.clear();loadingDates.clear();} }FuzzyKeyMemoryCache:
該緩存的作用就是假設緩存中的有一個key和要增加的keytemp相等。就從緩存中刪除該key指向的bitmap對象,然后把新的key對象增加到緩存中去。
詳細的邏輯例如以下:
@Overridepublic boolean put(String key, Bitmap value) {// Search equal key and remove this entrysynchronized (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:
又一個近期最久未使用緩存,在這里就不多說了,直接貼代碼: @Overridepublic 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);}}}
轉載于:https://www.cnblogs.com/cxchanpin/p/7070803.html
總結
以上是生活随笔為你收集整理的Android-Universal-Image-Loader学习笔记(3)--内存缓存的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 开药的意思?
- 下一篇: 贷款买车后要做抵押登记,抵押登记是什么要