Android 圖片加載系列:Glide加載圖片流程&緩存機(jī)制

上篇文章整理了一下 ImageView 直接展示圖片相關(guān)流程吠冤,這次再寫(xiě)一篇關(guān)于第三方圖片加載框架 Glide 的總結(jié)。很早之前就已經(jīng)看郭大神的博客研究了一把 Glide 昼捍,把相關(guān)的圖都整理了一遍基公,但是還未寫(xiě)文章,實(shí)話說(shuō)骗随,用心寫(xiě)好一篇文章總結(jié)蛤织,真的好花時(shí)間。

以下以我自身研究所得進(jìn)行整理鸿染,主在總結(jié)以及記錄一些刷新自己認(rèn)知的點(diǎn)指蚜。

基本用法

Glide 的使用方式非常簡(jiǎn)單,只需要一句代碼:

Glide.with(this).load(url).into(imageView);

這是我們常用的加載圖片姿勢(shì)涨椒,最關(guān)鍵的三步摊鸡,先 with() 確定圖片加載的生命周期,再 load() 加載不同類型的圖片資源蚕冬,最后 into() 展示到目標(biāo)View柱宦。這么一句簡(jiǎn)單的代碼,底層實(shí)現(xiàn)可是復(fù)雜得很播瞳,要整個(gè)都弄清楚,需要花費(fèi)很長(zhǎng)時(shí)間免糕,所以只沿一條主線開(kāi)始赢乓。

Glide 提供了豐富的API,功能強(qiáng)大石窑,整理如下:

  • 支持加載各種各樣的圖片資源牌芋,包括網(wǎng)絡(luò)圖片、本地圖片松逊、應(yīng)用資源躺屁、二進(jìn)制流、Uri對(duì)象等等经宏,load() 方法有多個(gè)方法重載犀暑;
  • 支持設(shè)置圖片加載前展示臨時(shí)占位圖,placeholder() 方法烁兰,以及圖片加載錯(cuò)誤時(shí)展示異常占位圖耐亏,error() 方法;
  • 支持靜態(tài)圖片和 gif 圖片格式沪斟,通過(guò) asBitmap()asGif() 方法指定加載哪種格式广辰;
  • 支持設(shè)置加載圖片的大小,比如網(wǎng)絡(luò)圖片下載之前設(shè)置圖片大小為View尺寸大小主之,然后加載壓縮后的大小到內(nèi)存择吊,避免大圖OOM,override() 方法槽奕;
  • 支持加載網(wǎng)絡(luò)圖片時(shí)各種緩存策略几睛,diskCacheStrategy() 方法;
  • 支持不同 ViewController 中圖片加載的生命周期,with() 方法史翘。
    Glide功能導(dǎo)圖.png

實(shí)現(xiàn)流程

Glide 的完整使用姿勢(shì)枉长,為鏈?zhǔn)浇Y(jié)構(gòu):

Glide.with(activity)      // RequestManager
   .load("")              // DrawableTypeRequest
   .asBitmap()            //  BitmapTypeRequest
   .placeholder(0)        // BitmapRequestBuilder<String, Bitmap>
   .diskCacheStrategy(DiskCacheStrategy.ALL)  // BitmapRequestBuilder
   .into(imageView);      // Target<Bitmap>

依照 with() -> load() -> intot() 這三步冀续,源碼中相關(guān)的類有這么幾個(gè):

  • Glide:?jiǎn)卫悾脕?lái)構(gòu)建 RequestBuilder必峰,并且持有 Engine洪唐,BitmapPool,DiskCache吼蚁,MemoryCache 實(shí)例
  • RequestManager:管理&開(kāi)始請(qǐng)求加載圖片凭需,該類實(shí)現(xiàn)了 LifecycleListener 生命周期接口,所以能根據(jù)Activity 和 Fragment 的生命周期決定 stop肝匆,start 以及 restart 圖片的加載粒蜈;
  • GenericRequestBuilder:A generic class that can handle setting options and staring loads for generic resource types.
  • Target:An interface that Glide can load a resource into and notify of relevant lifecycle events during a load.

除了 Glide 和 RequestManeger,其它兩個(gè)類還有很多不同類型的子類旗国,整理相關(guān)類圖如下:
Glie相關(guān)類圖.png

用一句簡(jiǎn)單的話來(lái)概括這幾個(gè)類之間的關(guān)系就是:Glide負(fù)責(zé)構(gòu)建含有生命周期的 RequestManager枯怖,RequestManager 根據(jù)load加載的不通圖片資源構(gòu)建具體的 ReuestBuilder,當(dāng)請(qǐng)求的圖片資源按照設(shè)置的規(guī)則(壓縮能曾、縮放度硝、緩存等)處理后,再回調(diào)給 Target寿冕,具體是通過(guò)何種 Target 子類設(shè)置蕊程,則根據(jù)不同的資源類型來(lái)確定。

注:類圖上方 RequestBuilder 和 下方 ImageViewTarget 子類相對(duì)應(yīng)驼唱,GlideDraeablrImageViewTarget 支持動(dòng)畫(huà)的加載藻茂,所以對(duì)應(yīng)為 GifRequestBuilder 請(qǐng)求加載的 gif 資源。

緩存策略

緩存在請(qǐng)求網(wǎng)絡(luò)圖片時(shí)能減少不必要的流量浪費(fèi)玫恳。Glide 緩存分為內(nèi)存緩存和硬盤(pán)緩存辨赐,這兩個(gè)緩存模塊的作用各不相同,內(nèi)存緩存的主要作用是 防止應(yīng)用重復(fù)的將圖片數(shù)據(jù)讀取到內(nèi)存京办,而硬盤(pán)緩存則是防止應(yīng)用重復(fù)從網(wǎng)絡(luò)或其他地方下載和讀取數(shù)據(jù)肖油。

關(guān)于緩存,就一定涉及到緩存 key 臂港。如何生成 key 呢森枪?查看 KeyFactory.buildKey() 方法。一般一張網(wǎng)絡(luò)圖片的唯一標(biāo)志是圖片 url 地址审孽,但是基于這張圖片加載時(shí)設(shè)置的一系列規(guī)則县袱,比如 override 設(shè)置了固定大小也會(huì)生成新的緩存 Key .

內(nèi)存緩存

Glide 默認(rèn)是開(kāi)啟了內(nèi)存緩存,可以通過(guò)代碼設(shè)置:

Glide.with(this).load(url).skipMemoryCache(true).into(iv);

skipMemoryCache() 方法傳入 true佑力,就表示禁止 Glide 的內(nèi)存功能式散。

內(nèi)存緩存經(jīng)常會(huì)用到 LruCache 算法,Glide 的內(nèi)存緩存用到的也是 LruCache 算法打颤,同時(shí)也用到了一種弱引用機(jī)制暴拄,共同完成內(nèi)存緩存漓滔。

追溯源碼至 Engine.load() 方法,這一步開(kāi)始決定是使用緩存數(shù)據(jù)還是直接重新下載圖片乖篷,整個(gè)流程如下:
內(nèi)存緩存策略.png

這里有個(gè)問(wèn)題:LruCache 只看到了取數(shù)據(jù)的過(guò)程响驴,那么何時(shí)會(huì)存數(shù)據(jù)呢?
A: Engine.onResourceReleased() 釋放資源時(shí)撕蔼,具體在于 acquire 引用計(jì)數(shù)器的作用:

  • 當(dāng)計(jì)數(shù)器>0豁鲤,說(shuō)明圖片正在使用,存在于 activeResources 弱引用map中鲸沮;
  • 經(jīng)過(guò) release() 后琳骡,若計(jì)數(shù)器=0,說(shuō)明圖片不再被使用讼溺,就會(huì)調(diào)用上述方法釋放資源楣号,此時(shí)在該方法中會(huì)將當(dāng)前沒(méi)有使用的資源緩存到 LruCache 中。
磁盤(pán)緩存

Glide 禁止磁盤(pán)緩存的代碼如下:

Glide.with(this).load(url).diskCacheStrategy(DiskCacheStrategy.NONE).into(iv);

先來(lái)說(shuō)說(shuō)幾種磁盤(pán)緩存的策略:

  • DiskCacheStrategy.NONE:表示不緩存任何內(nèi)容
  • DiskCacheStrategy.SOURCE:表示只緩存原始圖片
  • DiskCacheStrategy.RESULT:表示只緩存轉(zhuǎn)換后的圖片(默認(rèn)選項(xiàng))
  • DiskCacheStrategy.ALL:表示既緩存原始圖片怒坯,也緩存轉(zhuǎn)換后的圖片

注:Glide 加載一張圖時(shí)竖席,默認(rèn)不會(huì)展示原圖,而是會(huì)對(duì)圖片進(jìn)行壓縮和轉(zhuǎn)換敬肚,比如對(duì)圖片進(jìn)行尺寸壓縮到 目標(biāo)View大小。

磁盤(pán)緩存使用的也是 LRU 算法束析,對(duì)應(yīng)的實(shí)現(xiàn)工具為 DiskLruCache 艳馒,整個(gè)處理流程接著上面內(nèi)存緩存的流程開(kāi)始,也即是 新開(kāi) EngineRunnable 任務(wù)加載圖片员寇,這一步會(huì)先判斷是否進(jìn)行過(guò)磁盤(pán)緩存弄慰,若可以則直接從磁盤(pán)緩存取,否則重新下載蝶锋。流程如下:
磁盤(pán)緩存策略.png

關(guān)于 Glide 的緩存機(jī)制目前就到這里陆爽,簡(jiǎn)單總結(jié)就是:

  • 若允許內(nèi)存緩存,先從內(nèi)存LruCache中查找扳缕,若存在則將該資源添加到 activeResouces 弱引用map中然后返回慌闭,該 map 主要用來(lái)緩存當(dāng)前正在使用的資源,若不存在則判斷 activeResouces 弱引用map 中是否存在躯舔,若存在則返回驴剔,每次資源處于正在使用狀態(tài),則引用計(jì)數(shù)加一粥庄,若未使用丧失,則緩存到 LruCache 中;
  • 若內(nèi)存中不存在惜互,若允許磁盤(pán)緩存布讹,再?gòu)拇疟P(pán)緩存中查找琳拭;
  • 若磁盤(pán)中不存在,則直接下載描验,然后再根據(jù)磁盤(pán)緩存策略緩存原圖或是經(jīng)轉(zhuǎn)換后的圖到磁盤(pán)中白嘁。

總結(jié)

Glide 的功能之強(qiáng)大,還有很多沒(méi)整理到挠乳,更多來(lái)了解和源碼分析权薯,鏈接:https://blog.csdn.net/guolin_blog/article/details/53759439

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個(gè)濱河市睡扬,隨后出現(xiàn)的幾起案子盟蚣,更是在濱河造成了極大的恐慌,老刑警劉巖卖怜,帶你破解...
    沈念sama閱讀 217,826評(píng)論 6 506
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件屎开,死亡現(xiàn)場(chǎng)離奇詭異,居然都是意外死亡马靠,警方通過(guò)查閱死者的電腦和手機(jī)奄抽,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,968評(píng)論 3 395
  • 文/潘曉璐 我一進(jìn)店門(mén),熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái)甩鳄,“玉大人逞度,你說(shuō)我怎么就攤上這事∶羁校” “怎么了档泽?”我有些...
    開(kāi)封第一講書(shū)人閱讀 164,234評(píng)論 0 354
  • 文/不壞的土叔 我叫張陵,是天一觀的道長(zhǎng)揖赴。 經(jīng)常有香客問(wèn)我馆匿,道長(zhǎng),這世上最難降的妖魔是什么燥滑? 我笑而不...
    開(kāi)封第一講書(shū)人閱讀 58,562評(píng)論 1 293
  • 正文 為了忘掉前任渐北,我火速辦了婚禮,結(jié)果婚禮上铭拧,老公的妹妹穿的比我還像新娘赃蛛。我一直安慰自己,他們只是感情好搀菩,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,611評(píng)論 6 392
  • 文/花漫 我一把揭開(kāi)白布焊虏。 她就那樣靜靜地躺著,像睡著了一般秕磷。 火紅的嫁衣襯著肌膚如雪诵闭。 梳的紋絲不亂的頭發(fā)上,一...
    開(kāi)封第一講書(shū)人閱讀 51,482評(píng)論 1 302
  • 那天,我揣著相機(jī)與錄音疏尿,去河邊找鬼瘟芝。 笑死,一個(gè)胖子當(dāng)著我的面吹牛褥琐,可吹牛的內(nèi)容都是我干的锌俱。 我是一名探鬼主播,決...
    沈念sama閱讀 40,271評(píng)論 3 418
  • 文/蒼蘭香墨 我猛地睜開(kāi)眼敌呈,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼贸宏!你這毒婦竟也來(lái)了?” 一聲冷哼從身側(cè)響起磕洪,我...
    開(kāi)封第一講書(shū)人閱讀 39,166評(píng)論 0 276
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤吭练,失蹤者是張志新(化名)和其女友劉穎,沒(méi)想到半個(gè)月后析显,有當(dāng)?shù)厝嗽跇?shù)林里發(fā)現(xiàn)了一具尸體鲫咽,經(jīng)...
    沈念sama閱讀 45,608評(píng)論 1 314
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,814評(píng)論 3 336
  • 正文 我和宋清朗相戀三年谷异,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了分尸。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點(diǎn)故事閱讀 39,926評(píng)論 1 348
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡歹嘹,死狀恐怖箩绍,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情尺上,我是刑警寧澤材蛛,帶...
    沈念sama閱讀 35,644評(píng)論 5 346
  • 正文 年R本政府宣布,位于F島的核電站尖昏,受9級(jí)特大地震影響,放射性物質(zhì)發(fā)生泄漏构资。R本人自食惡果不足惜抽诉,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,249評(píng)論 3 329
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望吐绵。 院中可真熱鬧迹淌,春花似錦、人聲如沸己单。這莊子的主人今日做“春日...
    開(kāi)封第一講書(shū)人閱讀 31,866評(píng)論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)纹笼。三九已至纹份,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背蔓涧。 一陣腳步聲響...
    開(kāi)封第一講書(shū)人閱讀 32,991評(píng)論 1 269
  • 我被黑心中介騙來(lái)泰國(guó)打工件已, 沒(méi)想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留,地道東北人元暴。 一個(gè)月前我還...
    沈念sama閱讀 48,063評(píng)論 3 370
  • 正文 我出身青樓篷扩,卻偏偏與公主長(zhǎng)得像,于是被迫代替她去往敵國(guó)和親茉盏。 傳聞我的和親對(duì)象是個(gè)殘疾皇子鉴未,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 44,871評(píng)論 2 354

推薦閱讀更多精彩內(nèi)容

  • 一、簡(jiǎn)介 在泰國(guó)舉行的谷歌開(kāi)發(fā)者論壇上鸠姨,谷歌為我們介紹了一個(gè)名叫Glide的圖片加載庫(kù)铜秆,作者是bumptech。這...
    天天大保建閱讀 7,474評(píng)論 2 28
  • 7.1 壓縮圖片 一享怀、基礎(chǔ)知識(shí) 1羽峰、圖片的格式 jpg:最常見(jiàn)的圖片格式。色彩還原度比較好添瓷,可以支持適當(dāng)壓縮后保持...
    AndroidMaster閱讀 2,515評(píng)論 0 13
  • 上篇我們以加載一張網(wǎng)絡(luò)圖片為例梅屉,講解了Glide加載一張圖片的整體流程。為了更連貫的理解流程我們略過(guò)了一些細(xì)節(jié)鳞贷,包...
    嘎啦果安卓獸閱讀 50,677評(píng)論 7 46
  • 關(guān)于 Glide Glide是一個(gè)快速高效的Android圖片加載庫(kù)坯汤,注重于平滑的滾動(dòng)。Glide提供了易用的AP...
    android的那點(diǎn)事閱讀 2,682評(píng)論 0 13
  • 當(dāng)別人問(wèn)班里的同學(xué)你們班里有幾個(gè)人時(shí)搀愧,基本上大家都會(huì)毫不猶豫的回答54個(gè)人惰聂,實(shí)際上班里有55個(gè)人。 那多出來(lái)的人叫...
    周霸爺閱讀 760評(píng)論 22 13