今天填完離職表,幫着公司面試幾個幫着填坑的同行,聊着聊着就聊到了Glide,信誓旦旦的和我說,這塊很熟悉,以前在掘金社區裏,看過一個叫藍師傅寫的這塊的文章,基本細節都掌握😏。(一副勝利在望的表情,好吧,正巧我也看過,我們就問一問看的仔細狀況)java
(這貨口若懸河的說了一大通,從LruCache說到了LinkedHashMap,巴拉巴拉。。。我的建議這塊必定要簡述,面試時原理說的太多,第一不少細節會被打斷問到,第二點,說這麼多,給人的感受就是在背誦東西,原理歸納能力很弱或者感受根本就沒有本身的體會。)面試
Glide的緩存機制,主要分爲2種緩存,一種是內存緩存,一種是磁盤緩存。 之因此使用內存緩存的緣由是:防止應用重複將圖片讀入到內存,形成內存資源浪費。 之因此使用磁盤緩存的緣由是:防止應用重複的從網絡或者其餘地方下載和讀取數據。 正式由於有着這兩種緩存的結合,才構成了Glide極佳的緩存效果。算法
(先告訴人家有哪幾種緩存,主要是爲了什麼目的才用的緩存,而後能夠看着面試官,要麼等着他繼續問,若是他不問,等着你,這個時候你就能夠繼續的往細節處介紹)緩存
(記得,若是須要具體談原理時,要先宏觀,後細節)網絡
讀取一張圖片的時候,獲取順序: Lru算法緩存-》弱引用緩存-》磁盤緩存(若是設置了的話)app
當咱們的APP中想要加載某張圖片時,先去LruCache中尋找圖片,若是LruCache中有,則直接取出來使用,並將該圖片放入WeakReference中,若是LruCache中沒有,則去WeakReference中尋找,若是WeakReference中有,則從WeakReference中取出圖片使用,若是WeakReference中也沒有圖片,則從磁盤緩存/網絡中加載圖片。框架
注:圖片正在使用時存在於 activeResources 弱引用map中ide
流程以下圖 學習
將圖片緩存的時候,寫入順序: 弱引用緩存-》Lru算法緩存-》磁盤緩存中動畫
當圖片不存在的時候,先從網絡下載圖片,而後將圖片存入弱引用中,glide會採用一個acquired(int)變量用來記錄圖片被引用的次數, 當acquired變量大於0的時候,說明圖片正在使用中,也就是將圖片放到弱引用緩存當中; 若是acquired變量等於0了,說明圖片已經再也不被使用了,那麼此時會調用方法來釋放資源,首先會將緩存圖片從弱引用中移除,而後再將它put到LruResourceCache當中。 這樣也就實現了正在使用中的圖片使用弱引用來進行緩存,不在使用中的圖片使用LruCache來進行緩存的功能。
引深: 關於LruCache
最近最少使用算法,設定一個緩存大小,當緩存達到這個大小以後,會將最老的數據移除,避免圖片佔用內存過大致使OOM。 LruCache 內部用LinkHashMap存取數據,在雙向鏈表保證數據新舊順序的前提下,設置一個最大內存,往裏面put數據的時候,當數據達到最大內存的時候,將最老的數據移除掉,保證內存不超過設定的最大值。
關於LinkedHashMap
LinkHashMap 繼承HashMap,在 HashMap的基礎上,新增了雙向鏈表結構,每次訪問數據的時候,會更新被訪問的數據的鏈表指針,具體就是先在鏈表中刪除該節點,而後添加到鏈表頭header以前,這樣就保證了鏈表頭header節點以前的數據都是最近訪問的(從鏈表中刪除並非真的刪除數據,只是移動鏈表指針,數據自己在map中的位置是不變的)
(由於你緩存機制不管是看博客仍是看一些面試寶典,若是隻是考原理或者定義,光把上面的文字背誦下來就能夠了,可是背誦和真正的理解是兩回事,本身沒有造成感悟,不理解這個框架,只是一味的迎合面試,這個問題就能夠卡住你,另外千萬別和麪試官嘚瑟,果真,這個面試的哥們,這塊就卡住了,支支吾吾的半天沒答上來,果真是隻看了博客,沒真正的閱讀過源碼)
當咱們調整imageview的大小時,Picasso會無論imageview大小是什麼,老是直接緩存整張圖片,而Glide就不同了,它會爲每一個不一樣尺寸的Imageview緩存一張圖片,也就是說無論你的這張圖片有沒有加載過,只要imageview的尺寸不同,那麼Glide就會從新加載一次,這時候,它會在加載的imageview以前從網絡上從新下載,而後再緩存。
舉個例子,若是一個頁面的imageview是300 * 300像素,而另外一個頁面中的imageview是100 * 100像素,這時候想要讓兩個imageview像是同一張圖片,那麼Glide須要下載兩次圖片,而且緩存兩張圖片。
public <R> LoadStatus load() {
// 根據請求參數獲得緩存的鍵
EngineKey key = keyFactory.buildKey(model, signature, width, height, transformations,
resourceClass, transcodeClass, options);
}
複製代碼
看到了吧,緩存Key的生成條件之一就是控件的長寬。
(注意必定要審題,由於以前問了這個小夥,內存泄漏的緣由,無非是長生命週期引用了短生命週期的對象等等,而後忽然畫風一變,直接問了Glide加載圖片會不會引發圖片泄漏,這個小夥想也沒想,直接回答道會引發內存泄漏,能夠用LeakCanary檢測,巴拉巴拉。。。)
由於Glide 在加載資源的時候,若是是在 Activity、Fragment 這一類有生命週期的組件上進行的話,會建立一個透明的 RequestManagerFragment 加入到FragmentManager 之中,感知生命週期,當 Activity、Fragment 等組件進入不可見,或者已經銷燬的時候,Glide 會中止加載資源。
可是若是,是在非生命週期的組件上進行時,會採用Application 的生命週期貫穿整個應用,因此 applicationManager 只有在應用程序關閉的時候終止加載。
(這個孩子,總算是羞愧的低下了頭,一臉懵逼的和我說,這個我忘記了)
歸納來講,圖片加載包含封裝,解析,下載,解碼,變換,緩存,顯示等操做。
先寫到這,基本上問的也就這麼多了,要是再細扣,感受有些故意爲難了,面試的通常都是在30分鐘之內,感受對方會的,我會跳過,由於你會了,我就不必問了,浪費時間,感受不會的,問道你說出不會或者不清楚爲止,我也不會再在這方面細扣,緣由也是同樣,浪費時間。主要是發現每一個人的長處,及對待事情的態度。
另外其實吧,不必定都答的上來纔會要你,也不是由於答不上來就不要你,主要吧,仍是靠感受,好相處,人又不是太滑,性格nice,給人踏實的感受的,都會網開一面的。
下期我會仿照着Glide本身仿照一個,將Glide的主流程所涉及的,都會加上,這樣方便你們的理解。有興趣的能夠關注我。
仍是那句話 雖然更新時間沒準,快則半天,慢則半年,可是每一篇文章,我都深刻淺出,要麼豐富的流程圖,一看就懂,要麼就是一步一步仿照着寫,學習框架原理仍是那句話,先搞清楚爲何要這麼設計,可不能夠不這麼寫或者不加這個功能,根據情境分析,而後再去解讀這塊源碼邏輯,這樣纔會記的牢固