圖片框架-Glide的源碼和緩存原理簡述

比較流行的有ImageLoader,Picasso,Fresco,Glide。

1 ImageLoader是很早的圖片加載框架,支持圖片下載進度的監聽,支持View滾動過程中暫停加載。支持多種緩存策略比如最大先刪除,最少使用先刪除等。

2 Picasso簡潔輕量,支持圖片緩存使用的監控,支持優先級處理,支持延遲加載,自己不參與本地緩存而是交給OkHttp去實現。

3 Fresco框架較大,使用比較繁瑣,支持Gif圖片,支持流式顯示,類似於網頁模糊漸進式顯示圖片,兩個內存緩存和一個Native緩存構建三級緩存。

4 Glide 支持圖片緩存,支持Gif,Video。支持優先級處理,與Activity和Fragment生命週期同步,圖片默認是RGB_565,質量較差內存更小。功能更爲豐富。

項目中用的最多的是Glide:

Glide基本用法with,load,into。

with傳入的可以是當前上下文的對象。

load加載圖片,圖片可以是本地圖片,應用資源的圖片也可以是一張網絡圖片。

into傳入要展示圖片的控件。

with是Glide類的一個靜態方法,重載方法很多可以接收

Activity,Fragment,Context。

with方法裏面,首先會調用RequestManagerRetriever的靜態get方法得到RequestManagerRetriver對象。然後再調用該對象的get方法獲取RequestManager對象。靜態get方法中也有很多重載方法,主要分爲傳入Application參數和非Application參數,傳入Application參數是最簡單的情況,Glide只要持保和整個應用生命週期同步。

非Application參數不管是Activity,Fragment,最終都會向當前Activity傳入一個隱藏的Fragment,因爲Glide需要監控Activity的生命週期,Fragment依賴Activity生命週期並且是同步的,通過這個隱藏的Fragment就監聽到Activity生命週期。

load方法,with方法返回的是一個RequestManager對象,所以load方法在RequestManager類中,load方法也有很多重載,支持本地圖片,內存圖片,網絡圖片,只看加載url的load方法。首先調用了fromString方法,再調用load方法,傳入圖片url,fromString方法裏調用了loadGeneric方法,這個方法創建並返回了DrawableTypeRequest對象。

DrawableTypeRequest並沒有load方法,load在DrawableTypeRequest的父類DrawableTypeRequestBuildle中。大部分操作都在這個類中,比如placeholder佔位符,error,discacheStrategy等。

into方法是Glide圖片加載流程中邏輯最爲複雜的方法。

into方法在DrawableTypeRequestBuilder類中,裏面調用了super.into方法,真正的實現在DrawableTypeRequestBuilder的父類GenericRequestBuilder中,這個類包括了網絡請求,圖片解析,圖片解碼,bitmap生成,緩存處理,圖片壓縮等大量邏輯操作,最後的最後纔將圖片展示出來。

最關注的是Glide緩存:Glide分爲內存緩存和硬盤緩存兩個模塊,先從內存緩存查找再到硬盤緩存查找最後從網絡請求。

每種緩存必須有一個緩存key用來查詢,Glide緩存key是在Engine類load方法中實現,通過調用getId方法獲取一個字符串id,這個id就是要加載圖片的唯一標識。如果是網絡圖片就是圖片的url地址。然後這個id同傳入的參數構建出EngineKey也就是Glide的緩存key。

內存緩存:

1 LruCache算法緩存,最近最少使用原則,緩存原理是把最近使用的對象用強引用存儲到LinkHashMap中,把最近最少使用的對象在緩存值達到一定上限之前從緩存中移除。

2 弱引用緩存,緩存原理是把正在使用的圖片緩存到弱引用的HashMap中,主要防止正在使用的圖片被LruCache算法回收。

硬盤緩存:緩存策略有緩存轉換後的圖片和原始圖片,默認是緩存轉換後的。緩存算法依然是LruCache是谷歌封裝的DisLruCache。

如果有緩存文件的話會調用decodeFromCache從緩存中讀取,如果沒有調用decodeFromSource,從源頭讀取比如從網絡獲取。

遇到Glide緩存問題,項目的圖片資源都是放在七牛雲上面的,下載下來的圖片url地址後面有一個token參數,token作爲一個驗證身份的參數是時刻變化的。在Glide緩存中是通過圖片的url進行緩存的。結果造成了明明是一張圖片,因爲token的改變導致Glide緩存功能失效。

在查看源碼的時候,發現Glide緩存key是在Engine類中load方法中生成的。在這個方法中通過getId()方法返回了一個字符串id,發現這個id就是圖片的Url地址。然後找這個getId方法,發現在這個方法裏又調用了GlideUrl類中getCacheKey方法,在這個方法裏直接返回了圖片的url地址,最後通過繼承這個GlideUrl類重寫getCacheKey方法,去掉圖片的Url地址後面的token參數,然後將這個繼承類傳給Glide的load方法就可以解決Glide緩存問題了。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章