動腦學院Glide預習資料 緩存與解碼復用

Glide 使用簡明的流式語法API,大多數(shù)情況下,可能完成圖片的設置你只需要:
Glide.with(activity) .load(url) .into(imageView);

默認情況下,Glide 會在開始一個新的圖片請求之前檢查以下多級的緩存:
1. 活動資源 (Active Resources) 
2. 內(nèi)存緩存 (Memory Cache) 
3. 資源類型(Resource Disk Cache)
4. 原始數(shù)據(jù) (Data Disk Cache)

活動資源:如果當前對應的圖片資源正在使用,則這個圖片會被Glide放入活動緩存。
內(nèi)存緩存:如果圖片最近被加載過,并且當前沒有使用這個圖片,則會被放入內(nèi)存中
資源類型:  被解碼后的圖片寫入磁盤文件中,解碼的過程可能修改了圖片的參數(shù)(如:inSampleSize、inPreferredConfig)
原始數(shù)據(jù):  圖片原始數(shù)據(jù)在磁盤中的緩存(從網(wǎng)絡、文件中直接獲得的原始數(shù)據(jù))

在調(diào)用into之后,Glide會首先從Active Resources查找當前是否有對應的活躍圖片,沒有則查找內(nèi)存緩存,沒有則查找資源類型,沒有則查找數(shù)據(jù)來源。
緩存查找.png

相較于常見的內(nèi)存+磁盤緩存,Glide將其緩存分成了4層。

第一層 活動資源

當需要加載某張圖片能夠從內(nèi)存緩存中獲得的時候,在圖片加載時主動將對應圖片從內(nèi)存緩存中移除,加入到活動資源中。
這樣也可以避免因為達到內(nèi)存緩存最大值或者系統(tǒng)內(nèi)存壓力導致的內(nèi)存緩存清理,從而釋放掉活動資源中的圖片(recycle)。
活動資源中是一個”引用計數(shù)"的圖片資源的弱引用集合。

因為同一張圖片可能在多個地方被同時使用,每一次使用都會將引用計數(shù)+1,而當引用計數(shù)為0時候,則表示這個圖片沒有被使用也就是沒有強引用了。這樣則會將圖片從活動資源中移除,并加入內(nèi)存緩存。
加入內(nèi)存緩存.png

第二層 內(nèi)存緩存

內(nèi)存緩存默認使用LRU(緩存淘汰算法/最近最少使用算法),當資源從活動資源移除的時候,會加入此緩存。使用圖片的時候會主動從此緩存移除,加入活動資源。

LRU在Android support-v4中提供了LruCache工具類。
LruCache.png

構造LinkedHashMap的accessOrder設置為true。在使用的此map的時候,自動進行排序(每次get/put,會將使用的value放入鏈表header頭部)。LruCache會在每次get/put的時候判斷數(shù)據(jù)如果達到了maxSize,則會優(yōu)先刪除tail尾端的數(shù)據(jù)。
LRU.png

磁盤緩存同樣使用LRU算法。

第三、四層 磁盤緩存

Resource 緩存的是經(jīng)過解碼后的圖片,如果再使用就不需要再去進行解碼配置(BitmapFactory.Options),加快獲得圖片速度。比如原圖是一個100x100的ARGB_8888圖片,在首次使用的時候需要的是50x50的RGB_565圖片,那么Resource將50x50 RGB_565緩存下來,再次使用此圖片的時候就可以從 Resource 獲得。不需要去計算inSampleSize(縮放因子)。
Data 緩存的則是圖像原始數(shù)據(jù)。

Bitmap復用

如果緩存都不存在,那么會從源地址獲得圖片(網(wǎng)絡/文件)。而在解析圖片的時候會需要可以獲得BitmapPool(復用池),達到復用的效果。

復用前.png
復用后.png
復用效果如上。在未使用復用的情況下,每張圖片都需要一塊內(nèi)存。而使用復用的時候,如果存在能被復用的圖片會重復使用該圖片的內(nèi)存。
所以復用并不能減少程序正在使用的內(nèi)存大小。Bitmap復用,解決的是減少頻繁申請內(nèi)存帶來的性能(抖動、碎片)問題。
https://developer.android.google.cn/topic/performance/graphics/manage-memory.html
設置inBitmap復用.png
獲得可復用Bitmap.png
檢查Bitmap是否可復用.png

Google給出的案例可以看出:
使用方式為在解析的時候設置Options的inBitmap屬性。

  1. Bitmap的inMutable需要為true。
  2. Android 4.4及以上只需要被復用的Bitmap的內(nèi)存必須大于等于需要新獲得Bitmap的內(nèi)存,則允許復用此Bitmap。
  3. 4.4以下(3.0以上)則被復用的Bitmap與使用復用的Bitmap必須寬、高相等并且使用復用的Bitmap解碼時設置的inSampleSize為1,才允許復用。

因此Glide中,在每次解析一張圖片為Bitmap的時候(磁盤緩存、網(wǎng)絡/文件)會從其BitmapPool中查找一個可被復用的Bitmap。

BitmapPool是Glide中的Bitmap復用池,同樣適用LRU來進行管理。
當一個Bitmap從內(nèi)存緩存 被動 的被移除(內(nèi)存緊張、達到maxSize)的時候并不會被recycle。而是加入這個BitmapPool,只有從這個BitmapPool 被動
被移除的時候,Bitmap的內(nèi)存才會真正被recycle釋放。

原創(chuàng)文章,轉(zhuǎn)載請聯(lián)系作者哦~~

歡迎進群一起交流學習:Android開發(fā)交流群 481302961


2碼.png
?著作權歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務。

相關閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容