編輯:關於Android編程
LRU(Least Recently Used)最近最少使用算法
緩存保存了一個強引用(Android 2.3開始,垃圾回收器更傾向於回收弱引用和軟引用,軟引用和弱引用變得不可靠,Android 3.0中,圖片的數據會存儲在本地的內存當中,因而無法用一種可預見的方式將其釋放)限制值的數量. 每當值被訪問的時候,它會被移動到隊列的頭部. 當緩存已滿的時候加入新的值時,隊列中最後的值會出隊,可能被回收LRUCache內部維護主要是通過LinkedHashMap實現
這是一個安全的線程,多線程緩存通過同步實現?
默認情況下,緩存的大小是由值的數量決定,重寫sizeOf計算不同的值
如果你緩存值需要明確釋放,重寫entryRemoved()
int maxMemory = (int) Runtime.getRuntime().maxMemory();
int mCacheSize = maxMemory / 8;
//給LruCache分配1/8 4M
mMemoryCache = new LruCache(mCacheSize){
//必須重寫此方法,來測量Bitmap的大小
@Override
protected int sizeOf(String key, Bitmap value) {
return value.getRowBytes() * value.getHeight();
}
};
mMemoryCache.put(key, bitmap)
mMemoryCache.get(key)
這個類不允許有空的鍵值. get,put,remove 返回空值,key對應的值不在緩存中
構造函數,初始化了最大容量和LinkedHashMap
/**
* @param maxSize for caches that do not override {@link #sizeOf}, this is
* the maximum number of entries in the cache. For all other caches,
* this is the maximum sum of the sizes of the entries in this cache.
*/
public LruCache(int maxSize) {
if (maxSize <= 0) {
throw new IllegalArgumentException("maxSize <= 0");
}
this.maxSize = maxSize;
this.map = new LinkedHashMap(0, 0.75f, true);
}
這裡將LinkedHashMap最後一個參數(accessOrder)設置為true,將accessOrder設置為true時,可以使遍歷順序和訪問順序一致,其內部雙向鏈表將會按照近期最少訪問到近期最多訪問的順序排列Entry對象
put方法,首先不允許鍵值為空,然後是線程安全,put的次數加一,size增加,以鍵值對的形式存入LinkedHashMap,如果之前已經存在了這個鍵值對,size減少成原來的大小,如果容量超過maxsize,將會刪除最近很少訪問的entry
/** * Caches {@code value} for {@code key}. The value is moved to the head of * the queue. * * @return the previous value mapped by {@code key}. */ public final V put(K key, V value) { if (key == null || value == null) { throw new NullPointerException("key == null || value == null"); } V previous; synchronized (this) { putCount++; size += safeSizeOf(key, value); previous = map.put(key, value); if (previous != null) { size -= safeSizeOf(key, previous); } } if (previous != null) { entryRemoved(false, key, previous, value); } trimToSize(maxSize); return previous; }
put方法有一個很關鍵的地方超過最大值是會刪除最近最少訪問的
trimToSize首先線程安全,檢查當前大小是否大於最大值,如果大於最大值,從LinkedHashMap中去除最近最少(循環刪除鏈表首部元素)被訪問的元素,獲得鍵值,刪除
/**
* 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.
*/
public void trimToSize(int maxSize) {
while (true) {
K key;
V value;
synchronized (this) {
if (size < 0 || (map.isEmpty() && size != 0)) {
throw new IllegalStateException(getClass().getName()
+ ".sizeOf() is reporting inconsistent results!");
}
if (size <= maxSize) {
break;
}
Map.Entry toEvict = map.eldest();
if (toEvict == null) {
break;
}
key = toEvict.getKey();
value = toEvict.getValue();
map.remove(key);
size -= safeSizeOf(key, value);
evictionCount++;
}
entryRemoved(true, key, value, null);
}
}
get方法,首先key不能為空,線程安全,根據key,從LinkedHashMap中獲得value,不為空的話返回,為空的話,創建一個key,創建失敗返回null,創建成功,在LinkedHashMap中創建鍵值對,存在就覆蓋,不存在size增加,返回value值
/** * Returns the value for {@code key} if it exists in the cache or can be * created by {@code #create}. If a value was returned, it is moved to the * head of the queue. This returns null if a value is not cached and cannot * be created. */ public final V get(K key) { if (key == null) { throw new NullPointerException("key == null"); } V mapValue; synchronized (this) { mapValue = map.get(key); if (mapValue != null) { hitCount++; return mapValue; } missCount++; } /* * Attempt to create a value. This may take a long time, and the map * may be different when create() returns. If a conflicting value was * added to the map while create() was working, we leave that value in * the map and release the created value. */ V createdValue = create(key); if (createdValue == null) { return null; } synchronized (this) { createCount++; mapValue = map.put(key, createdValue); if (mapValue != null) { // There was a conflict so undo that last put map.put(key, mapValue); } else { size += safeSizeOf(key, createdValue); } } if (mapValue != null) { entryRemoved(false, key, createdValue, mapValue); return mapValue; } else { trimToSize(maxSize); return createdValue; } }
核心代碼分析完畢,想知道LinkedHashMap,請聽下回哔哔
概述:SurfaceView是Android中極為重要的繪圖容器,SurfaceView的圖像繪制是放在主線程之外的另一個線程中完成的。除了繪圖,SurfaceView還
什麼是廣播在Android中,Broadcast是一種廣泛運用的在應用程序之間傳輸信息的機制。我們拿廣播電台來做個比方。我們平常使用收音機收音是這樣的:許許多多不同的廣播
前言Android的源碼公開策略豐富了手持設備的多樣性,但隨之而來的卻是較為嚴重的”碎片化”——版本繁多、尺寸多樣、功能定
百度視頻播放器是百度公司推出的一款為Android用戶精心優化的免費視頻應用,集視頻搜索、視頻推薦、離線觀看、劇集提醒等等眾多創新優秀功能於一身。它不僅僅是