跟著源碼學(xué)設(shè)計(jì):Glide框架及源碼解析(三)

前言

近期研究了一下Glide的圖片加載框架,在這里和大家分享一下。由于代碼研讀有限站蝠,難免有錯誤的地方吟孙,了解的童鞋還望指正藻治。學(xué)習(xí)小組QQ群: 193765960雏节。

本篇是Glide框架及源碼解析的第三篇件蚕,更多文章敬請關(guān)注后續(xù)文章。如果這篇文章對大家學(xué)習(xí)Glide有幫助,還望大家多多轉(zhuǎn)載。

版權(quán)歸作者所有,如有轉(zhuǎn)發(fā)泪酱,請注明文章出處:http://www.reibang.com/u/d43d948bef39

相關(guān)文章:

跟著源碼學(xué)設(shè)計(jì):Glide框架及源碼解析(一)
跟著源碼學(xué)設(shè)計(jì):Glide框架及源碼解析(二)
跟著源碼學(xué)設(shè)計(jì):Glide框架及源碼解析(三)
跟著源碼學(xué)設(shè)計(jì):Glide框架及源碼解析(四)
跟著源碼學(xué)設(shè)計(jì):Glide框架及源碼解析(五)

Glide內(nèi)存緩存機(jī)制

在之前的兩篇中我們剖析了Glide的生命周期綁定機(jī)制和Glide的請求管理機(jī)制。接下來按說應(yīng)該講到request實(shí)際請求資源并回調(diào)刷新界面這一塊了,但是為了更好的理解Glide在這一塊的設(shè)計(jì),我先大致的講一講Glide的內(nèi)存緩存和管理機(jī)制。
不同于其他常見網(wǎng)絡(luò)加載框架只有LruCatch一種緩存機(jī)制,Glide內(nèi)存為三塊(非常牛逼巧妙的設(shè)計(jì)):

  • ActiveResourceCache:緩存當(dāng)前正在使用的資源(注意是弱引用)
  • LruResourceCache: 緩存最近使用過但是當(dāng)前未使用的資源透敌,LRU算法
  • BitmapPool:緩存所有被釋放的圖片撵术,內(nèi)存復(fù)用,LRU算法

注意:

  • LruResourceCache和ActiveResourceCache設(shè)計(jì)是為了盡可能的資源復(fù)用
  • BitmapPool的設(shè)計(jì)目的是為了盡可能的內(nèi)存復(fù)用

說的比較抽象古毛,是不是懵逼了?別急服傍,上圖:


Glide內(nèi)存緩存及管理機(jī)制
  • 當(dāng)我們需要顯示某個資源時钞支,Glide會先去查找LruResourceCache柬采,找到了則將資源從LruResourceCache移除加入到ActiveResourceCache;

  • LruResourceCache找不到資源則查找ActiveResourceCache。

  • 如果在ActiveResourceCache也找不到合適的資源,則會根據(jù)加載策略從硬盤或者網(wǎng)絡(luò)加載資源力试。

  • 獲取數(shù)據(jù)后Glide會從BitmapPool中找尋合適的可供內(nèi)存復(fù)用的廢棄recycled bitmap(找不到則會重新創(chuàng)建bitmap對象),然后刷新bitmap的數(shù)據(jù)饮亏。

  • bitmap被轉(zhuǎn)換封裝為Resource緩存入ActiveResourceCache和Request對象中百侧。

  • Request的target會獲取resource中引用的bitmap并展示。

  • 當(dāng)target的資源需要release時突硝,resource會根據(jù)緩存策略被緩存到LruResourceCache,同時ActiveResourceCache中的弱引用會被刪除。如果拧揽,該資源不能緩存到LruResourceCache,則資源將被recycle到BitmapPool漱贱。

  • 當(dāng)需要回收內(nèi)存時(比如系統(tǒng)內(nèi)存不足或者生命周期結(jié)束)配猫,LruResourceCache將根據(jù)LRU算法recycle一些resource到BitmapPool。

  • BitmapPool會根據(jù)緩存池的尺寸和recycled resource的緩存策略來緩存resource的bitmap冯丙。

  • BitmapPool會根據(jù)LRU算法和緩存池的尺寸來釋放一些老舊資源。

  • 當(dāng)系統(tǒng)GC時挨厚,則會回收可回收的資源釋放內(nèi)存

這樣就完成了一個資源的完整的循環(huán)疫剃。

BitmapPool的內(nèi)存復(fù)用機(jī)制

知識儲備:

  • BitmapFactory.Options.inBitmap是AndroiD3.0新增的一個屬性,如果設(shè)置了這個屬性則會重用這個Bitmap的內(nèi)存從而提升性能棉胀。
  • 在SDK 11 -> 18之間,重用的bitmap大小必須是一致的诚隙,例如給inBitmap賦值的圖片大小為100-100,那么新申請的bitmap必須也為100-100才能夠被重用犯建。從SDK 19開始,新申請的bitmap大小必須小于或者等于已經(jīng)賦值過的bitmap大小瓜客。
  • 新申請的bitmap與舊的bitmap必須有相同的解碼格式适瓦,例如大家都是8888的,如果前面的bitmap是8888谱仪,那么就不能支持4444與565格式的bitmap了

使用inbitmap前玻熙,內(nèi)存占用情況

使用inbitmap前,內(nèi)存占用情況

使用inbitmap后疯攒,內(nèi)存占用情況

使用inbitmap后嗦随,內(nèi)存占用情況

下面看一下核心代碼:Downsampler的downsampleWithSize()方法

private Bitmap downsampleWithSize(MarkEnforcingInputStream is, RecyclableBufferedInputStream  bufferedStream,
BitmapFactory.Options options, BitmapPool pool, int inWidth, int inHeight, int sampleSize,
DecodeFormat decodeFormat) {
  // Prior to KitKat, the inBitmap size must exactly match the size of the bitmap we're decoding.
  Bitmap.Config config = getConfig(is, decodeFormat);
  options.inSampleSize = sampleSize;
  options.inPreferredConfig = config;
  if ((options.inSampleSize == 1 || Build.VERSION_CODES.KITKAT <= Build.VERSION.SDK_INT) && shouldUsePool(is)) {
    int targetWidth = (int) Math.ceil(inWidth / (double) sampleSize);
    int targetHeight = (int) Math.ceil(inHeight / (double) sampleSize);
    // BitmapFactory will clear out the Bitmap before writing to it, so getDirty is safe.
    setInBitmap(options, pool.getDirty(targetWidth, targetHeight, config));
  }
  return decodeStream(is, bufferedStream, options);
}
 
@TargetApi(Build.VERSION_CODES.HONEYCOMB)
private static void setInBitmap(BitmapFactory.Options options, Bitmap recycled) {
  if (Build.VERSION_CODES.HONEYCOMB <= Build.VERSION.SDK_INT) {
    options.inBitmap = recycled;
  }
}

讓我們先看一下我們最常見到的LruMemoryCache機(jī)制

ActiveResourceCache的設(shè)計(jì)
  • 如圖,當(dāng)系統(tǒng)內(nèi)存不足時敬尺,LruMemoryCache會根據(jù)LRU算法移除一些資源(bitmap)
  • 針對移除的資源枚尼,系統(tǒng)在GC時會回收資源(bitmap)以釋放內(nèi)存
  • 當(dāng)應(yīng)用再次需要次資源時,需要重新分配內(nèi)存砂吞,重新對資源文件進(jìn)行解析生成bitmap
    1)這樣會造成內(nèi)存抖動署恍;
    2)比較耗費(fèi)時間,影響流暢度(GC也比較頻繁)

讓我們再來看一下Glide的機(jī)制

ActiveResourceCache的設(shè)計(jì)
  • 如圖蜻直,當(dāng)系統(tǒng)內(nèi)存不足時盯质,LruResourceCache會根據(jù)LRU算法移除一些資源(resource)到BitmapPool
  • 到BitmapPool會根據(jù)LRU算法移除一些資源(bitmap)
  • 當(dāng)應(yīng)用再次需要資源時,會優(yōu)先復(fù)用到BitmapPool中的bitmap對象(復(fù)用其內(nèi)存)概而,只需刷新bitmap的像素數(shù)據(jù)
    1)這樣能有效地降低內(nèi)存抖動呼巷;
    2)由于很多情況下可以復(fù)用廢棄bitmap的內(nèi)存,因此避免了內(nèi)存分配等造成的性能損耗赎瑰,系統(tǒng)比較流暢
    3)降低了系統(tǒng)GC的頻率
    4)LruResourceCache和BitmapPool中都是當(dāng)前不在使用的資源王悍,做整體的資源回收那叫一個酸爽。

(本篇是Glide框架及源碼解析的第三篇乡范,更多文章敬請關(guān)注后續(xù)文章配名。版權(quán)歸作者所有啤咽,如有轉(zhuǎn)發(fā),請注明文章出處:原文鏈接

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末渠脉,一起剝皮案震驚了整個濱河市宇整,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌芋膘,老刑警劉巖鳞青,帶你破解...
    沈念sama閱讀 216,651評論 6 501
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異为朋,居然都是意外死亡臂拓,警方通過查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,468評論 3 392
  • 文/潘曉璐 我一進(jìn)店門习寸,熙熙樓的掌柜王于貴愁眉苦臉地迎上來胶惰,“玉大人,你說我怎么就攤上這事霞溪》踔停” “怎么了?”我有些...
    開封第一講書人閱讀 162,931評論 0 353
  • 文/不壞的土叔 我叫張陵鸯匹,是天一觀的道長坊饶。 經(jīng)常有香客問我,道長殴蓬,這世上最難降的妖魔是什么匿级? 我笑而不...
    開封第一講書人閱讀 58,218評論 1 292
  • 正文 為了忘掉前任,我火速辦了婚禮染厅,結(jié)果婚禮上痘绎,老公的妹妹穿的比我還像新娘。我一直安慰自己糟秘,他們只是感情好简逮,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,234評論 6 388
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著尿赚,像睡著了一般散庶。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上凌净,一...
    開封第一講書人閱讀 51,198評論 1 299
  • 那天悲龟,我揣著相機(jī)與錄音,去河邊找鬼冰寻。 笑死须教,一個胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播轻腺,決...
    沈念sama閱讀 40,084評論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼乐疆,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了贬养?” 一聲冷哼從身側(cè)響起挤土,我...
    開封第一講書人閱讀 38,926評論 0 274
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎误算,沒想到半個月后仰美,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 45,341評論 1 311
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡儿礼,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,563評論 2 333
  • 正文 我和宋清朗相戀三年咖杂,在試婚紗的時候發(fā)現(xiàn)自己被綠了。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片蚊夫。...
    茶點(diǎn)故事閱讀 39,731評論 1 348
  • 序言:一個原本活蹦亂跳的男人離奇死亡诉字,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出知纷,到底是詐尸還是另有隱情奏窑,我是刑警寧澤,帶...
    沈念sama閱讀 35,430評論 5 343
  • 正文 年R本政府宣布屈扎,位于F島的核電站,受9級特大地震影響撩匕,放射性物質(zhì)發(fā)生泄漏鹰晨。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,036評論 3 326
  • 文/蒙蒙 一止毕、第九天 我趴在偏房一處隱蔽的房頂上張望模蜡。 院中可真熱鬧,春花似錦扁凛、人聲如沸忍疾。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,676評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽卤妒。三九已至,卻和暖如春字币,著一層夾襖步出監(jiān)牢的瞬間则披,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 32,829評論 1 269
  • 我被黑心中介騙來泰國打工洗出, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留士复,地道東北人。 一個月前我還...
    沈念sama閱讀 47,743評論 2 368
  • 正文 我出身青樓翩活,卻偏偏與公主長得像阱洪,于是被迫代替她去往敵國和親便贵。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 44,629評論 2 354

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