Android開源框架Universal-Image-Loader學(xué)習(xí)三――UsingFreqLimitedMemoryCache源碼閱讀
來(lái)源:程序員人生 發(fā)布時(shí)間:2015-06-01 08:41:25 閱讀次數(shù):4924次
Universal-Image-Loader的內(nèi)存緩存策略

1. 只使用的是強(qiáng)援用緩存
- LruMemoryCache(這個(gè)類就是這個(gè)開源框架默許的內(nèi)存緩存類,緩存的是bitmap的強(qiáng)援用)
2.使用強(qiáng)援用和弱援用相結(jié)合的緩存有
- UsingFreqLimitedMemoryCache(如果緩存的圖片總量超過(guò)限定值,先刪除使用頻率最小的bitmap)
- LRULimitedMemoryCache(這個(gè)也是使用的lru算法,和LruMemoryCache不同的是,他緩存的是bitmap的弱援用)
- FIFOLimitedMemoryCache(先進(jìn)先出的緩存策略,當(dāng)超過(guò)設(shè)定值,先刪除最早加入緩存的bitmap)
- LargestLimitedMemoryCache(當(dāng)超過(guò)緩存限定值,先刪除最大的bitmap對(duì)象)
- LimitedAgeMemoryCache(當(dāng) bitmap加入緩存中的時(shí)間超過(guò)我們?cè)O(shè)定的值,將其刪除)
3.只使用弱援用緩存
- WeakMemoryCache(這個(gè)類緩存bitmap的總大小沒有限制,唯1不足的地方就是不穩(wěn)定,緩存的圖片容易被回收掉)
繼承關(guān)系:

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、先來(lái)看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、現(xiàn)在1般使用MemoryCache替換MemoryCacheAware:
MemoryCacheAware源碼:
public interface MemoryCache extends MemoryCacheAware<String, Bitmap> {
}
3、BaseMemoryCache 源碼:
/*為memory cache提供1些基本功能;提供object的援用(非強(qiáng)援用)存儲(chǔ)*/
public abstract class BaseMemoryCache implements MemoryCache {
/** 存儲(chǔ)objects的非強(qiáng)援用,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的存儲(chǔ)。所有存儲(chǔ)的bitmap的總內(nèi)存大小不超過(guò)限定值
* 注:該cache使用強(qiáng)援用和弱援用來(lái)存儲(chǔ)Bitmaps;
* 強(qiáng)援用――對(duì)限額內(nèi)的bitmaps
* 弱利用――對(duì)其他的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,1個(gè)提供原子操作的Integer的類,使得操作線程安全*/
private final AtomicInteger cacheSize;
/**
* 包括存儲(chǔ)objects的強(qiáng)援用。每一個(gè)object都添加到最尾端;如果hard cache的大超過(guò)了限定值,首真?zhèn)€object將會(huì)被刪除
*(但它仍然存在在softMap中,而且可以隨時(shí)被GC回收)
// 返回1個(gè)synchronizes封裝的線程安全的List
public static <T> List<T> synchronizedList(List<T> list)*/
private final List<Bitmap> hardCache = Collections.synchronizedList(new LinkedList<Bitmap>());
/**構(gòu)造函數(shù):sizeLimit單位bytes */
public LimitedMemoryCache(int sizeLimit) {
this.sizeLimit = sizeLimit;
cacheSize = new AtomicInteger();
/**檢測(cè)避免sizeLimit值設(shè)置過(guò)大 */
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); //抽象函數(shù),返回Bitmap的大小值
int sizeLimit = getSizeLimit(); //返回sizeLimit
int curCacheSize = cacheSize.get();//返回cacheSize確當(dāng)前值
/**如果添加的bitmap的size大于sizeLimit,則直接不將其添加至hard cache*/
if (valueSize < sizeLimit) {
/**判斷新添加的Object的valueSize加上當(dāng)前cache中已有object的curCacheSize超過(guò)限定值,則會(huì)刪除適當(dāng)Bitmap*/
while (curCacheSize + valueSize > sizeLimit) {
Bitmap removedValue = removeNext(); //abstract函數(shù),返回需要?jiǎng)h除的下1個(gè)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源碼:(關(guān)鍵在于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:使用強(qiáng)援用和弱援用;
* 強(qiáng)援用: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對(duì)應(yīng)的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 {
//簡(jiǎn)單的比較得到最小值
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);
}
}
生活不易,碼農(nóng)辛苦
如果您覺得本網(wǎng)站對(duì)您的學(xué)習(xí)有所幫助,可以手機(jī)掃描二維碼進(jìn)行捐贈(zèng)