Android高級開發工程師面試系列-如何對圖片進行緩存?

面試題:如何對圖片進行緩存?

題目剖析:
1.網絡、磁盤,內存緩存
2.緩存算法分析
3.以熟悉的框架爲例分析它的緩存機制
4.要有驗證算法效果的意識

一.圖片加載過程
先從內存中讀取,如果沒有從磁盤中讀取,如果沒有從網絡獲取顯示
在這裏插入圖片描述
二.緩存算法分析
設計緩存算法,需要考慮以下幾點:
1.哪些應該保存?
獲取成本,緩存成本,緩存的價值
首先看獲取的成本高不高,獲取成本高,緩存就非常值,其次看緩存成本,本身緩存內存就很小,如果緩存的文件是個1個g的,緩存就非常不值了,最後隨着時間的推移,如果緩存的文件使用率不高,那緩存的價值就不高。

2.哪些應該丟棄?什麼時候丟棄?
一、LRU算法:
這個時候我們的LRU算法就登場了(最近最少使用算法),LRU算法的工作流程:假設我們設計的只能緩存4個,通過以下演算看下LRU的緩存流程:
1.訪問順序:A→B→D
緩存媒介:D→B→A
2.訪問順序:A→B→D→D
緩存媒介:D→B→A
3.訪問順序:A→B→D→D→BA→B→D→D→B
緩存媒介:B→D→A
4.訪問順序:A→B→D→D→B→C
緩存媒介:C→B→D→A
5.訪問順序:A→B→D→D→B→C→A
緩存媒介:A→C→B→D
6.訪問順序:A→B→D→D→B→C→A→E
緩存媒介:E→A→C→B
整個緩存的流程分爲以上六步:
LruCache(Least Recently Used)算法的核心思想就是最近最少使用算法。他在算法的內部維護了一個LinkHashMap的鏈表,通過put數據的時候判斷是否內存已經滿了,如果滿了,則將最近最少使用的數據給剔除掉,從而達到內存不會爆滿的狀態。我們發現經過以上幾步緩存之後,緩存內容D被幹掉了。
這裏有一個疑問,爲什麼LruCache內部原理的實現需要用到LinkHashMap來存儲數據吶?
因爲LinkHashMap內部是一個數組加雙向鏈表的形式來存儲數據,他能夠保證插入時候的數據和取出來的時候數據的順序的一致性。也就是說,我們以什麼樣的順序插入數據,就會以什麼樣的順序取出數據。並且更重要的一點是,當我們通過get方法獲取數據的時候,這個獲取的數據會從隊列中跑到隊列頭來,從而很好的滿足我們LruCache的算法設計思想。
我們先看下LruCache算法的構造方法。
public LruCache(int maxSize) {
if (maxSize <= 0) {
throw new IllegalArgumentException(“maxSize <= 0”);
}
this.maxSize = maxSize;
this.map = new LinkedHashMap<K, V>(0, 0.75f, true);
}
從構造方法的源碼我們可以看到,在這段代碼中我們主要做了兩件事。第一是判斷下傳遞來的最大分配內存大小是否小於零,如果小於零則拋出異常,因爲我們如果傳入一個小於零的內存大小就沒有意義了。之後在構造方法內存就new了一個LinkHashMap集合,從而得知LruCache內部實現原理果然是基於LinkHashMap來實現的,這裏需要注意new LinkedHashMap<K, V>(0, 0.75f, true);時最後一個喫參數傳的true,通過源碼我們發現當爲true時,當內存不足時,LinkedHashMap會自動刪除最後一個元素。

二、LFU算法(最近不經常使用原則):
如果用LFU算法來實現上面的緩存流程,則到最後緩存中的內容應該爲E→D→B→A,我們發現最後把C給丟棄了,因爲LFU遵循最近不經常使用原則,也就是說使用次數最少的,當內存不足時會首先被幹掉。
我們熟悉的Glide圖片加載框架就是使用LRUCache算法,內部也是基於LinkedhashMap來實現的。

總結:當面試時面試官問圖片的緩存機制時,我們可以以Glide爲例說下圖片的加載過程,解釋下LRUCache算法緩存原理以及內部基於LinkHashMap來實現的原因。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章