Android 【手撕Glide】--Glide緩存機(jī)制(精簡(jiǎn)總結(jié))

本文源碼解析基于Glide 4.6.1

系列文章
Android 【手撕Glide】--Glide緩存機(jī)制
Android 【手撕Glide】--Glide緩存機(jī)制(面試)
Android 【手撕Glide】--Glide是如何關(guān)聯(lián)生命周期的饭弓?

引入緩存的目的

  • 1油猫、減少流量消耗装盯,加快響應(yīng)速度;
  • 2士鸥、Bitmap 的創(chuàng)建/銷毀比較耗內(nèi)存,可能會(huì)導(dǎo)致頻繁GC;使用緩存可以更加高效地加載 Bitmap蛾洛,減少卡頓。

Glide緩存流程

Glide緩存分為內(nèi)存緩存和磁盤(pán)緩存雁芙,其中內(nèi)存緩存是由弱引用+LruCache組成轧膘。

取的順序是:弱引用、LruCache兔甘、磁盤(pán)
存的順序是:磁盤(pán)谎碍、弱引用、LruCache

這張親手制作的圖片洞焙,方便大家更直觀的理解緩存機(jī)制的整體流程蟆淀,結(jié)合文末總結(jié)效果更佳。喜歡的記得點(diǎn)贊澡匪!

Glide緩存機(jī)制.png

注意:關(guān)于緩存的存取的入口在Engine這個(gè)類中

內(nèi)存緩存原理

概述

1熔任、弱引用是由這樣一個(gè)HashMap維護(hù),key是緩存的key唁情,這個(gè)key由圖片url疑苔、width、height等10來(lái)個(gè)參數(shù)組成甸鸟;value是圖片資源對(duì)象的弱引用形式惦费。

Map<Key, ResourceWeakReference> activeEngineResources = new HashMap<>();

2、LruCache是由一個(gè)LinkedHashMap維護(hù)抢韭,根據(jù)Lru算法來(lái)管理圖片薪贫。大致的原理是利用linkHashMap鏈表的特性,把最近使用過(guò)的文件插入到鏈表尾部篮绰,沒(méi)使用的圖片在頭部后雷;然后當(dāng)圖片大小到達(dá)預(yù)先設(shè)置的一個(gè)閾值的時(shí)候 ,按算法刪除鏈表頭部的數(shù)據(jù)。由于篇幅有限臀突,這里不講解LruCache和DiskLruCache的底層原理勉抓,這里推薦一篇 圖解LinkedHashMap原理

這是Glide自定義的LruCache

#LruCache
Map<T, Y> cache = new LinkedHashMap<>(100, 0.75f, true);

存取原理
取數(shù)據(jù)
在內(nèi)存緩存中有一個(gè)概念叫圖片引用計(jì)數(shù)器 ,具體來(lái)說(shuō)是在EngineResource中定義一個(gè)acquired變量用來(lái)記錄圖片被引用的次數(shù)候学,調(diào)用acquire()方法會(huì)讓變量加1藕筋,調(diào)用release()方法會(huì)讓變量減1。

獲取圖片資源是先從弱引用取緩存梳码,拿到的話隐圾,引用計(jì)數(shù)+1;沒(méi)有的話從LruCache中拿緩存掰茶,拿到的話暇藏,引用計(jì)數(shù)也是+1,同時(shí)把圖片從LruCache緩存轉(zhuǎn)移到弱應(yīng)用緩存池中濒蒋;再?zèng)]有的話就通過(guò)EngineJob開(kāi)啟線程池去加載圖片盐碱,拿到的話,引用計(jì)數(shù)也是+1沪伙,會(huì)把圖片放到弱引用瓮顽。

存數(shù)據(jù)
很明顯,這是加載圖片之后的事情围橡。通過(guò)EngineJob開(kāi)啟線程池去加載圖片暖混,取到數(shù)據(jù)之后,會(huì)回調(diào)到主線程翁授,把圖片存到弱引用拣播。當(dāng)圖片不再使用的時(shí)候,比如說(shuō)暫停請(qǐng)求或者加載完畢或者清除資源時(shí)黔漂,就會(huì)將其從弱引用中轉(zhuǎn)移到LruCache緩存池中诫尽。總結(jié)一下,就是正在使用中的圖片使用弱引用來(lái)進(jìn)行緩存炬守,暫時(shí)不用的圖片使用LruCache來(lái)進(jìn)行緩存的功能;同一張圖片只會(huì)出現(xiàn)在弱引用LruCache中的一個(gè)。

為什么要引入弱引用剂跟?

  1. 避免正在使用的圖片被回收
  2. 分壓策略减途,減少Lrucache 中trimToSize的概率。如果正在remove的是張大圖曹洽,lrucache正好處在臨界點(diǎn)鳍置,此時(shí)remove操作,將延緩Lrucache的trimToSize操作送淆;
  3. 提高效率:弱引用用的是HashMap税产,Lrucache用的是LinkedHashMap,從訪問(wèn)效率而言,肯定是HashMap更高。

磁盤(pán)緩存原理(DiskLruCache)

Glide磁盤(pán)緩存策略(4.x)

  • DiskCacheStrategy.DATA: 只緩存原始圖片辟拷;
  • DiskCacheStrategy.RESOURCE:只緩存轉(zhuǎn)換過(guò)后的圖片撞羽;
  • DiskCacheStrategy.ALL:既緩存原始圖片,也緩存轉(zhuǎn)換過(guò)后的圖片衫冻;對(duì)于遠(yuǎn)程圖片诀紊,緩存 DATA和 RESOURCE;對(duì)于本地圖片隅俘,只緩存 RESOURCE邻奠;
  • DiskCacheStrategy.NONE:不緩存任何內(nèi)容;
  • DiskCacheStrategy.AUTOMATIC:默認(rèn)策略为居,嘗試對(duì)本地和遠(yuǎn)程圖片使用最佳的策略碌宴。當(dāng)下載網(wǎng)絡(luò)圖片時(shí),使用DATA(原因很簡(jiǎn)單蒙畴,對(duì)本地圖片的處理可比網(wǎng)絡(luò)要容易得多)唧喉;對(duì)于本地圖片,使用RESOURCE忍抽。

如果在內(nèi)存緩存中沒(méi)獲取到數(shù)據(jù)會(huì)通過(guò)EngineJob開(kāi)啟線程池去加載圖片,這里有2個(gè)關(guān)鍵類:DecodeJobEngineJob八孝。EngineJob 內(nèi)部維護(hù)了線程池,用來(lái)管理資源加載鸠项,當(dāng)資源加載完畢的時(shí)候通知回調(diào)干跛; DecodeJob是線程池中的一個(gè)任務(wù)。

磁盤(pán)緩存是通過(guò)DiskLruCache來(lái)管理的,根據(jù)緩存策略祟绊,會(huì)有2種類型的圖片楼入,DATA(原始圖片)和 RESOURCE(轉(zhuǎn)換后的圖片)。磁盤(pán)緩存依次通過(guò)ResourcesCacheGenerator牧抽、SourceGenerator嘉熊、DataCacheGenerator來(lái)獲取緩存數(shù)據(jù)。ResourcesCacheGenerator獲取的是轉(zhuǎn)換過(guò)的緩存數(shù)據(jù)扬舒;SourceGenerator獲取的是未經(jīng)轉(zhuǎn)換的原始的緩存數(shù)據(jù)阐肤;DataCacheGenerator是通過(guò)網(wǎng)絡(luò)獲取圖片數(shù)據(jù)再按照按照緩存策略的不同去緩存不同的圖片到磁盤(pán)上。

總結(jié)(干貨)

Glide緩存分為弱引用+ LruCache+ DiskLruCache讲坎,其中讀取數(shù)據(jù)的順序是:弱引用 > LruCache > DiskLruCache>網(wǎng)絡(luò)孕惜;寫(xiě)入緩存的順序是:網(wǎng)絡(luò) --> DiskLruCache-->弱引用 --> LruCache

內(nèi)存緩存分為弱引用的和 LruCache ,其中正在使用的圖片使用弱引用緩存晨炕,暫時(shí)不使用的圖片用 LruCache緩存衫画,這一點(diǎn)是通過(guò) 圖片引用計(jì)數(shù)器(acquired變量)來(lái)實(shí)現(xiàn)的,詳情可以看內(nèi)存緩存的小結(jié)瓮栗。

磁盤(pán)緩存就是通過(guò)DiskLruCache實(shí)現(xiàn)的削罩,根據(jù)緩存策略的不同會(huì)獲取到不同類型的緩存圖片瞄勾。它的邏輯是:先從轉(zhuǎn)換后的緩存中取弥激;沒(méi)有的話再?gòu)脑嫉模](méi)有轉(zhuǎn)換過(guò)的)緩存中拿數(shù)據(jù)进陡;再?zèng)]有的話就從網(wǎng)絡(luò)加載圖片數(shù)據(jù),獲取到數(shù)據(jù)之后秆撮,再依次緩存到磁盤(pán)和弱引用四濒。

參考:
面試官:簡(jiǎn)歷上最好不要寫(xiě)Glide,不是問(wèn)源碼那么簡(jiǎn)單
原來(lái)面試的時(shí)候?qū)懢℅lide职辨,這樣問(wèn)我這樣答

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末盗蟆,一起剝皮案震驚了整個(gè)濱河市,隨后出現(xiàn)的幾起案子舒裤,更是在濱河造成了極大的恐慌喳资,老刑警劉巖,帶你破解...
    沈念sama閱讀 218,755評(píng)論 6 507
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件腾供,死亡現(xiàn)場(chǎng)離奇詭異仆邓,居然都是意外死亡,警方通過(guò)查閱死者的電腦和手機(jī)伴鳖,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,305評(píng)論 3 395
  • 文/潘曉璐 我一進(jìn)店門(mén)节值,熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái),“玉大人榜聂,你說(shuō)我怎么就攤上這事搞疗。” “怎么了须肆?”我有些...
    開(kāi)封第一講書(shū)人閱讀 165,138評(píng)論 0 355
  • 文/不壞的土叔 我叫張陵匿乃,是天一觀的道長(zhǎng)。 經(jīng)常有香客問(wèn)我豌汇,道長(zhǎng)浑厚,這世上最難降的妖魔是什么职员? 我笑而不...
    開(kāi)封第一講書(shū)人閱讀 58,791評(píng)論 1 295
  • 正文 為了忘掉前任筛峭,我火速辦了婚禮崔梗,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘柜思。我一直安慰自己岩调,他們只是感情好,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,794評(píng)論 6 392
  • 文/花漫 我一把揭開(kāi)白布赡盘。 她就那樣靜靜地躺著,像睡著了一般缰揪。 火紅的嫁衣襯著肌膚如雪陨享。 梳的紋絲不亂的頭發(fā)上葱淳,一...
    開(kāi)封第一講書(shū)人閱讀 51,631評(píng)論 1 305
  • 那天,我揣著相機(jī)與錄音抛姑,去河邊找鬼赞厕。 笑死,一個(gè)胖子當(dāng)著我的面吹牛定硝,可吹牛的內(nèi)容都是我干的皿桑。 我是一名探鬼主播,決...
    沈念sama閱讀 40,362評(píng)論 3 418
  • 文/蒼蘭香墨 我猛地睜開(kāi)眼蔬啡,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼诲侮!你這毒婦竟也來(lái)了?” 一聲冷哼從身側(cè)響起箱蟆,我...
    開(kāi)封第一講書(shū)人閱讀 39,264評(píng)論 0 276
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤沟绪,失蹤者是張志新(化名)和其女友劉穎,沒(méi)想到半個(gè)月后空猜,有當(dāng)?shù)厝嗽跇?shù)林里發(fā)現(xiàn)了一具尸體绽慈,經(jīng)...
    沈念sama閱讀 45,724評(píng)論 1 315
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,900評(píng)論 3 336
  • 正文 我和宋清朗相戀三年辈毯,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了坝疼。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點(diǎn)故事閱讀 40,040評(píng)論 1 350
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡谆沃,死狀恐怖钝凶,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情管毙,我是刑警寧澤腿椎,帶...
    沈念sama閱讀 35,742評(píng)論 5 346
  • 正文 年R本政府宣布,位于F島的核電站夭咬,受9級(jí)特大地震影響啃炸,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜卓舵,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,364評(píng)論 3 330
  • 文/蒙蒙 一南用、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧掏湾,春花似錦裹虫、人聲如沸。這莊子的主人今日做“春日...
    開(kāi)封第一講書(shū)人閱讀 31,944評(píng)論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)。三九已至尊浪,卻和暖如春匣屡,著一層夾襖步出監(jiān)牢的瞬間封救,已是汗流浹背。 一陣腳步聲響...
    開(kāi)封第一講書(shū)人閱讀 33,060評(píng)論 1 270
  • 我被黑心中介騙來(lái)泰國(guó)打工捣作, 沒(méi)想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留誉结,地道東北人。 一個(gè)月前我還...
    沈念sama閱讀 48,247評(píng)論 3 371
  • 正文 我出身青樓券躁,卻偏偏與公主長(zhǎng)得像惩坑,于是被迫代替她去往敵國(guó)和親。 傳聞我的和親對(duì)象是個(gè)殘疾皇子也拜,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 44,979評(píng)論 2 355