內(nèi)存緩存
緩存與內(nèi)存回收機(jī)制有關(guān),java中有四種與垃圾回收(gc)有關(guān)的引用:強(qiáng)引用(StrongReference)综液、軟引用(SoftReference)、弱引用(WeakReference)和虛引用(PhantomReference)。
強(qiáng)引用(StrongReference)
強(qiáng)引用是最普遍的一種引用曹锨,在java中使用new關(guān)鍵字生成的對象就是強(qiáng)引用,對于強(qiáng)引用亩冬,java垃圾回收機(jī)制不會(huì)將其回收艘希,當(dāng)內(nèi)存不足時(shí),java虛擬機(jī)寧肯拋出OutOfMemoryError錯(cuò)誤也不會(huì)隨意回收強(qiáng)引用的對象硅急。
軟引用(SoftReference)
對于軟引用覆享,當(dāng)內(nèi)存足夠時(shí),不會(huì)回收軟引用的對象营袜,但是當(dāng)內(nèi)存空間不足時(shí)撒顿,就會(huì)回收這些對象。
弱引用(WeakReference)
弱引用荚板,相對于軟引用來說凤壁,更容易被回收機(jī)制回收,當(dāng)垃圾回收機(jī)制掃描內(nèi)存空間時(shí)跪另,如果發(fā)現(xiàn)弱引用對象拧抖,不論當(dāng)前的內(nèi)存是否充足,都會(huì)立即將其回收免绿,釋放內(nèi)存空間唧席。
虛引用(PhantomReference)
虛引用不同于其他引用,其并不會(huì)決定對象的生命周期。如果一個(gè)對象僅持有虛引用淌哟,那么它就和沒有任何引用一樣迹卢,在任何時(shí)候都可能被垃圾回收器回收。
Universal-Image-Loader中的緩存機(jī)制
1徒仓、LRU(Least Recently Used)最近最久未使用頁面置換算法
LRU是操作系統(tǒng)中頁面置換算法的一種腐碱,其核心是,對于每一個(gè)頁面掉弛,設(shè)置一個(gè)時(shí)間字段症见,用來記錄這個(gè)頁面自上次被訪問以來所經(jīng)歷的時(shí)間t,當(dāng)出現(xiàn)缺頁中斷(也就是內(nèi)存不足)時(shí)狰晚,將t值最大的頁面刪除筒饰。
2、Universal-Image-Loader中緩存機(jī)制
(1)只使用的是強(qiáng)引用緩存
LruMemoryCache(使用LRU算法壁晒,緩存對象的是bitmap的強(qiáng)引用)
(2)使用強(qiáng)引用和弱引用相結(jié)合的緩存有
UsingFreqLimitedMemoryCache(如果緩存的圖片總量超過限定值瓷们,先刪除使用頻率最小的bitmap)
LRULimitedMemoryCache(這個(gè)也是使用的lru算法,和LruMemoryCache不同的是秒咐,他緩存的是bitmap的弱引用)
FIFOLimitedMemoryCache(先進(jìn)先出的緩存策略谬晕,當(dāng)超過設(shè)定值,先刪除最先加入緩存的bitmap)
LargestLimitedMemoryCache(當(dāng)超過緩存限定值携取,先刪除最大的bitmap對象)
LimitedAgeMemoryCache(當(dāng) bitmap加入緩存中的時(shí)間超過我們設(shè)定的值攒钳,將其刪除)
(3)只使用弱引用緩存
WeakMemoryCache(這個(gè)類緩存bitmap的總大小沒有限制,唯一不足的地方就是不穩(wěn)定雷滋,緩存的圖片容易被回收掉)
LruMemoryCache源碼分析
package com.nostra13.universalimageloader.cache.memory.impl;
import android.graphics.Bitmap;
import com.nostra13.universalimageloader.cache.memory.MemoryCache;
import java.util.Collection;
import java.util.HashSet;
import java.util.LinkedHashMap;
import java.util.Map;
/**
* A cache that holds strong references to a limited number of Bitmaps. Each time a Bitmap is accessed, it is moved to
* the head of a queue. When a Bitmap is added to a full cache, the Bitmap at the end of that queue is evicted and may
* become eligible for garbage collection.<br />
* <br />
* <b>NOTE:</b> This cache uses only strong references for stored Bitmaps.
*
* @author Sergey Tarasevich (nostra13[at]gmail[dot]com)
* @since 1.8.1
*/
public class LruMemoryCache implements MemoryCache {
private final LinkedHashMap<String, Bitmap> map;
private final int maxSize;
/** Size of this cache in bytes */
private int size;
/** @param maxSize Maximum sum of the sizes of the Bitmaps in this cache */
public LruMemoryCache(int maxSize) {
if (maxSize <= 0) {
throw new IllegalArgumentException("maxSize <= 0");
}
this.maxSize = maxSize;
this.map = new LinkedHashMap<String, Bitmap>(0, 0.75f, true);
}
/**
* Returns the Bitmap for {@code key} if it exists in the cache. If a Bitmap was returned, it is moved to the head
* of the queue. This returns null if a Bitmap is not cached.
*/
@Override
public final Bitmap get(String key) {
if (key == null) {
throw new NullPointerException("key == null");
}
synchronized (this) {
return map.get(key);
}
}
/** Caches {@code Bitmap} for {@code key}. The Bitmap is moved to the head of the queue. */
@Override
public final boolean put(String key, Bitmap value) {
if (key == null || value == null) {
throw new NullPointerException("key == null || value == null");
}
synchronized (this) {
size += sizeOf(key, value);
Bitmap previous = map.put(key, value);
if (previous != null) {
size -= sizeOf(key, previous);
}
}
trimToSize(maxSize);
return true;
}
/**
* Remove the eldest entries until the total of remaining entries is at or below the requested size.
*
* @param maxSize the maximum size of the cache before returning. May be -1 to evict even 0-sized elements.
*/
private void trimToSize(int maxSize) {
while (true) {
String key;
Bitmap value;
synchronized (this) {
if (size < 0 || (map.isEmpty() && size != 0)) {
throw new IllegalStateException(getClass().getName() + ".sizeOf() is reporting inconsistent results!");
}
if (size <= maxSize || map.isEmpty()) {
break;
}
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);
}
}
}
/** Removes the entry for {@code key} if it exists. */
@Override
public final Bitmap remove(String key) {
if (key == null) {
throw new NullPointerException("key == null");
}
synchronized (this) {
Bitmap previous = map.remove(key);
if (previous != null) {
size -= sizeOf(key, previous);
}
return previous;
}
}
@Override
public Collection<String> keys() {
synchronized (this) {
return new HashSet<String>(map.keySet());
}
}
@Override
public void clear() {
trimToSize(-1); // -1 will evict 0-sized elements
}
/**
* Returns the size {@code Bitmap} in bytes.
* <p/>
* An entry's size must not change while it is in the cache.
*/
private int sizeOf(String key, Bitmap value) {
return value.getRowBytes() * value.getHeight();
}
@Override
public synchronized final String toString() {
return String.format("LruCache[maxSize=%d]", maxSize);
}
}
在源碼中LinkedHashMap作為LRU算法的緩存不撑,LinkedHashMap是HashMap的一個(gè)子類,它保留插入的順序晤斩,LinkedHashMap實(shí)現(xiàn)與HashMap的不同之處在于焕檬,后者維護(hù)著一個(gè)運(yùn)行于所有條目的雙重鏈接列表。此鏈接列表定義了迭代順序澳泵,該迭代順序可以是插入順序或者是訪問順序实愚。
默認(rèn)是按插入順序排序,如果指定按訪問順序排序兔辅,那么調(diào)用get方法后腊敲,會(huì)將這次訪問的元素移至鏈表尾部,不斷訪問可以形成按訪問順序排序的鏈表维苔∨龈ǎ可以重寫removeEldestEntry方法返回true值指定插入元素時(shí)移除最老的元素。
this.map = new LinkedHashMap<String, Bitmap>(0, 0.75f, true);
構(gòu)造方法中第一個(gè)參數(shù)代表LinkedHashMap初始容量介时,第二個(gè)參數(shù)0.75f是加載因子乎赴,第三個(gè)參數(shù)是訪問順序忍法,默認(rèn)為false即插入順序,true為訪問順序榕吼。
LruMemoryCache中維護(hù)了一個(gè)所有bitmap的size和,如果size超過設(shè)定的maxSize勉失,就會(huì)將最近最久未使用的圖片緩存刪除羹蚣。
在源碼的put方法中調(diào)用了HashMap中的put方法:
public V put(K key, V value) {
if (key == null)
return putForNullKey(value);
int hash = hash(key.hashCode());
int i = indexFor(hash, table.length);
for (Entry<K,V> e = table[i]; e != null; e = e.next) {
Object k;
if (e.hash == hash && ((k = e.key) == key || key.equals(k))) {
V oldValue = e.value;
e.value = value;
e.recordAccess(this);
return oldValue;
}
}
modCount++;
addEntry(hash, key, value, i);
return null;
}
void recordAccess(HashMap<K,V> m) {
LinkedHashMap<K,V> lm = (LinkedHashMap<K,V>)m;
//當(dāng)LinkedHashMap按訪問排序時(shí)
if (lm.accessOrder) {
lm.modCount++;
//移除當(dāng)前節(jié)點(diǎn)
remove();
//將當(dāng)前節(jié)點(diǎn)插入到頭結(jié)點(diǎn)前面
addBefore(lm.header);
}
}
/**
* 移除節(jié)點(diǎn),并修改前后引用
*/
private void remove() {
before.after = after;
after.before = before;
}
/**
* 將當(dāng)前節(jié)點(diǎn)插入到existingEntry的前面
*/
private void addBefore(Entry<K,V> existingEntry) {
after = existingEntry;
before = existingEntry.before;
before.after = this;
after.before = this;
}
HashMap中put方法源碼乱凿,當(dāng)HashMap中存在這個(gè)value時(shí)顽素,會(huì)將這個(gè)value返回,否則返回null徒蟆,所以當(dāng)map.put(key, value)
返回值不為空時(shí)胁出,需要減去剛加入的圖片size。當(dāng)返回為null時(shí)段审,將bitmap加入到LinkedHashMap中全蝶,返回為bitmap時(shí),直接使用該bitmap寺枉。recordAccess(HashMap<K,V> m)
在HashMap的put和get方法中抑淫,會(huì)調(diào)用該方法,在HashMap中該方法為空姥闪,在LinkedHashMap中始苇,當(dāng)按訪問順序排序時(shí),該方法會(huì)將當(dāng)前節(jié)點(diǎn)插入到鏈表尾部(頭結(jié)點(diǎn)的前一個(gè)節(jié)點(diǎn))筐喳,否則不做任何事(最近使用的bitmap會(huì)移動(dòng)到雙向鏈表的尾部)催式。
LRU算法實(shí)現(xiàn)的核心是private void trimToSize(int maxSize)
函數(shù)中不斷判斷當(dāng)前size是否大于maxSize,當(dāng)超過maxSize時(shí)避归,會(huì)將LinkedHashMap中的第一個(gè)元素刪除荣月,其就是最近最久未使用的bitmap。
使用LinkedHashMap可以很容易構(gòu)造一個(gè)基于LRU算法的緩存槐脏。
UsingFreqLimitedMemoryCache源碼分析
/*******************************************************************************
* Copyright 2011-2014 Sergey Tarasevich
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*******************************************************************************/
package com.nostra13.universalimageloader.cache.memory;
import android.graphics.Bitmap;
import java.lang.ref.Reference;
import java.util.*;
/**
* Base memory cache. Implements common functionality for memory cache. Provides object references (
* {@linkplain Reference not strong}) storing.
*
* @author Sergey Tarasevich (nostra13[at]gmail[dot]com)
* @since 1.0.0
*/
public abstract class BaseMemoryCache implements MemoryCache {
/** Stores not strong references to objects */
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);
}
/*******************************************************************************
* Copyright 2011-2014 Sergey Tarasevich
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*******************************************************************************/
package com.nostra13.universalimageloader.cache.memory;
import android.graphics.Bitmap;
import com.nostra13.universalimageloader.utils.L;
import java.util.Collections;
import java.util.LinkedList;
import java.util.List;
import java.util.concurrent.atomic.AtomicInteger;
/**
* Limited cache. Provides object storing. Size of all stored bitmaps will not to exceed size limit (
* {@link #getSizeLimit()}).<br />
* <br />
* <b>NOTE:</b> This cache uses strong and weak references for stored Bitmaps. Strong references - for limited count of
* Bitmaps (depends on cache size), weak references - for all other cached Bitmaps.
*
* @author Sergey Tarasevich (nostra13[at]gmail[dot]com)
* @see BaseMemoryCache
* @since 1.0.0
*/
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;
private final AtomicInteger cacheSize;
/**
* Contains strong references to stored objects. Each next object is added last. If hard cache size will exceed
* limit then first object is deleted (but it continue exist at {@link #softMap} and can be collected by GC at any
* time)
*/
private final List<Bitmap> hardCache = Collections.synchronizedList(new LinkedList<Bitmap>());
/** @param sizeLimit Maximum size for cache (in bytes) */
public LimitedMemoryCache(int sizeLimit) {
this.sizeLimit = sizeLimit;
cacheSize = new AtomicInteger();
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);
}
}
@Override
public boolean put(String key, Bitmap value) {
boolean putSuccessfully = false;
// Try to add value to hard cache
int valueSize = getSize(value);
int sizeLimit = getSizeLimit();
int curCacheSize = cacheSize.get();
if (valueSize < sizeLimit) {
while (curCacheSize + valueSize > sizeLimit) {
Bitmap removedValue = removeNext();
if (hardCache.remove(removedValue)) {
curCacheSize = cacheSize.addAndGet(-getSize(removedValue));
}
}
hardCache.add(value);
cacheSize.addAndGet(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
public void clear() {
hardCache.clear();
cacheSize.set(0);
super.clear();
}
protected int getSizeLimit() {
return sizeLimit;
}
protected abstract int getSize(Bitmap value);
protected abstract Bitmap removeNext();
}
/*******************************************************************************
* Copyright 2011-2014 Sergey Tarasevich
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*******************************************************************************/
package com.nostra13.universalimageloader.cache.memory.impl;
import android.graphics.Bitmap;
import com.nostra13.universalimageloader.cache.memory.LimitedMemoryCache;
import java.lang.ref.Reference;
import java.lang.ref.WeakReference;
import java.util.Collections;
import java.util.HashMap;
import java.util.Map;
import java.util.Map.Entry;
import java.util.Set;
/**
* 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.<br />
* <br />
* <b>NOTE:</b> This cache uses strong and weak references for stored Bitmaps. Strong references - for limited count of
* Bitmaps (depends on cache size), weak references - for all other cached Bitmaps.
*
* @author Sergey Tarasevich (nostra13[at]gmail[dot]com)
* @since 1.0.0
*/
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);
// Increment usage count for value if value is contained in hardCahe
if (value != null) {
Integer usageCount = usingCounts.get(value);
if (usageCount != null) {
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) {
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);
}
}
UsingFreqLimitedMemoryCache繼承自LimitedMemoryCach囊拜,而LimitedMemoryCach繼承自BaseMemoryCache躲庄。BaseMemoryCache中維護(hù)了Map<String, Reference<Bitmap>> softMap
包含軟引用類型bitmap的softMap,定義了softMap的get、put占哟、remove和clear方法。
LimitedMemoryCache繼承BaseMemoryCache章贞,其中定義了MAX_NORMAL_CACHE_SIZE_IN_MB
页响、MAX_NORMAL_CACHE_SIZE
、內(nèi)存大小限制sizeLimit和List<Bitmap> hardCache(用來維護(hù)該算法的bitmap列表)鸟缕。當(dāng)進(jìn)行put操作時(shí)晶框,首先判斷put的bitmap是否比限制的sizeLimit還大排抬,如果小于sizeLimit,循環(huán)判斷當(dāng)前緩存的cacheSize(AtomicInteger是一個(gè)提供原子操作的Integer類授段,通過線程安全的方式操作加減蹲蒲。AtomicInteger提供原子操作來進(jìn)行Integer的使用,因此十分適合高并發(fā)情況下的使用侵贵。)加上要put的bitmap的size是否大于sizeLimit届搁,如果大于sizeLimit,則調(diào)用算法刪除頻率最小的bitmap窍育。
removeNext()卡睦,在UsingFreqLimitedMemoryCache中實(shí)現(xiàn),其使用Map<Bitmap, Integer> usingCounts保存內(nèi)存中bitmap的使用次數(shù)漱抓。當(dāng)調(diào)用removeNext()方法時(shí)表锻,遍歷Map<Bitmap, Integer> usingCounts,找到使用次數(shù)最少的bitmap并返回乞娄。
FIFOLimitedMemoryCache源碼分析
/*******************************************************************************
* Copyright 2011-2014 Sergey Tarasevich
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*******************************************************************************/
package com.nostra13.universalimageloader.cache.memory.impl;
import android.graphics.Bitmap;
import com.nostra13.universalimageloader.cache.memory.LimitedMemoryCache;
import java.lang.ref.Reference;
import java.lang.ref.WeakReference;
import java.util.Collections;
import java.util.LinkedList;
import java.util.List;
/**
* 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 cache clearing is processed by FIFO principle.<br />
* <br />
* <b>NOTE:</b> This cache uses strong and weak references for stored Bitmaps. Strong references - for limited count of
* Bitmaps (depends on cache size), weak references - for all other cached Bitmaps.
*
* @author Sergey Tarasevich (nostra13[at]gmail[dot]com)
* @since 1.0.0
*/
public class FIFOLimitedMemoryCache extends LimitedMemoryCache {
private final List<Bitmap> queue = Collections.synchronizedList(new LinkedList<Bitmap>());
public FIFOLimitedMemoryCache(int sizeLimit) {
super(sizeLimit);
}
@Override
public boolean put(String key, Bitmap value) {
if (super.put(key, value)) {
queue.add(value);
return true;
} else {
return false;
}
}
@Override
public Bitmap remove(String key) {
Bitmap value = super.get(key);
if (value != null) {
queue.remove(value);
}
return super.remove(key);
}
@Override
public void clear() {
queue.clear();
super.clear();
}
@Override
protected int getSize(Bitmap value) {
return value.getRowBytes() * value.getHeight();
}
@Override
protected Bitmap removeNext() {
return queue.remove(0);
}
@Override
protected Reference<Bitmap> createReference(Bitmap value) {
return new WeakReference<Bitmap>(value);
}
}
FIFOLimitedMemoryCache也繼承了LimitedMemoryCache瞬逊,并維護(hù)了一個(gè)LinkedList<Bitmap>,與ArrayList相比补胚,LinkedList中包含了一個(gè)雙向循環(huán)鏈表码耐,提供了類似棧和隊(duì)列的操作。
LinkedList的add方法:
public boolean add(E e) {
addBefore(e, header);
return true;
}
private Entry<E> addBefore(E e, Entry<E> entry) {
Entry<E> newEntry = new Entry<E>(e, entry, entry.previous);
newEntry.previous.next = newEntry;
newEntry.next.previous = newEntry;
size++;
modCount++;
return newEntry;
}
向LinkedList中插入元素時(shí)溶其,是將元素插入到了header的后面addBefore(e, header);
骚腥,即將元素插入到鏈表的尾部。
public E remove(int index) {
return remove(entry(index));
}
private Entry<E> entry(int index) {
if (index < 0 || index >= size)
throw new IndexOutOfBoundsException("Index: "+index+
", Size: "+size);
Entry<E> e = header;
// 根據(jù)這個(gè)判斷決定從哪個(gè)方向遍歷這個(gè)鏈表
if (index < (size >> 1)) {
for (int i = 0; i <= index; i++)
e = e.next;
} else {
// 可以通過header節(jié)點(diǎn)向前遍歷瓶逃,說明這個(gè)一個(gè)循環(huán)雙向鏈表束铭,header的previous指向鏈表的最后一個(gè)節(jié)點(diǎn),這也驗(yàn)證了構(gòu)造方法中對于header節(jié)點(diǎn)的前后節(jié)點(diǎn)均指向自己的解釋
for (int i = size; i > index; i--)
e = e.previous;
}
return e;
}
FIFOLimitedMemoryCache的removeNext()方法中queue.remove(0);是將雙向循環(huán)列表的第一個(gè)元素刪除厢绝。由此可知由于插入元素時(shí)是向雙向循環(huán)列表中尾部插入新元素契沫,刪除時(shí),刪除列表的第一個(gè)元素昔汉,即先進(jìn)先出算法懈万。
除此之外,LargestLimitedMemoryCache和LimitedAgeMemoryCach都繼承了LimitedMemoryCache靶病,是強(qiáng)引用和弱引用相結(jié)合的緩存会通,因?yàn)锽aseMemoryCache中維護(hù)了一個(gè)軟引用的HashMap<String, Reference<Bitmap>>(),LimitedMemoryCache中維護(hù)了一個(gè)強(qiáng)引用的LinkedList<Bitmap>()娄周,只是具體實(shí)現(xiàn)算法不同而已涕侈。
WeakMemoryCache源碼分析
/*******************************************************************************
* Copyright 2011-2014 Sergey Tarasevich
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*******************************************************************************/
package com.nostra13.universalimageloader.cache.memory.impl;
import android.graphics.Bitmap;
import com.nostra13.universalimageloader.cache.memory.BaseMemoryCache;
import java.lang.ref.Reference;
import java.lang.ref.WeakReference;
/**
* Memory cache with {@linkplain WeakReference weak references} to {@linkplain android.graphics.Bitmap bitmaps}<br />
* <br />
* <b>NOTE:</b> This cache uses only weak references for stored Bitmaps.
*
* @author Sergey Tarasevich (nostra13[at]gmail[dot]com)
* @since 1.5.3
*/
public class WeakMemoryCache extends BaseMemoryCache {
@Override
protected Reference<Bitmap> createReference(Bitmap value) {
return new WeakReference<Bitmap>(value);
}
}
WeakMemoryCache繼承BaseMemoryCache,返回一個(gè) WeakReference<Bitmap>煤辨,其他方法使用父類方法裳涛。
參考文章:
http://blog.csdn.net/xiaanming/article/details/27525741
http://www.cnblogs.com/children/archive/2012/10/02/2710624.html
http://blog.csdn.net/jzhf2012/article/details/8540543