您好,登錄后才能下訂單哦!
這幾天在很多地方看到有聊Glide的,想起前年還是去年的時候面試的時候也有問到Glide相關(guān)的,正好今天趁著周五來聊一聊面試中Glide的那些東西
請查看完整的PDF版
(更多完整項目下載。未完待續(xù)。源碼。圖文知識后續(xù)上傳github。)
可以點擊關(guān)于我聯(lián)系我獲取完整PDF
LruCache
是個泛型類,主要原理是:把最近使用的對象用強引用存儲在 LinkedHashMap
中,當(dāng)緩存滿時,把最近最少使用的對象從內(nèi)存中移除,并提供 get/put 方法完成緩存的獲取和添加LruCache
是線程安全的,因為使用了 synchronized 關(guān)鍵字。
當(dāng)調(diào)用 put()方法,將元素加到鏈表頭,如果鏈表中沒有該元素,大小不變,如果沒有,需調(diào)用 trimToSize
方法判斷是否超過最大緩存量,trimToSize()
方法中有一個 while(true)死循環(huán),如果緩存大小大于最大的緩存值,會不斷刪除 LinkedHashMap
中隊尾的元素,即最少訪問的,直到緩存大小小于最大緩存值。當(dāng)調(diào)用 LruCache
的 get 方法時,LinkedHashMap
會調(diào)用recordAccess
方法將此元素加到鏈表頭部
1)Glide.with(context)創(chuàng)建了一個 RequestManager
,同時實現(xiàn)加載圖片與組件生命周期綁定:
在 Activity 上創(chuàng)建一個透明的 ReuqestManagerFragment
加入到 FragmentManager
中,通過添加的 Fragment 感知Activty\Fragment
的生命周期。因為添加到 Activity 中的 Fragment 會跟隨Activity 的生命周期。在 RequestManagerFragment
中的相應(yīng)生命周期方法中通過 liftcycle
傳遞給在 lifecycle
中注冊的 LifecycleListener
2)RequestManager.load(url)
創(chuàng)建了一個 RequestBuilder<T>
對象 T 可以是 Drawable
對象或是 ResourceType
等
3 ) RequestBuilder.into(view)
-->into(glideContext.buildImageViewTarget(view, transcodeClass))
返 回 的 是 一 個DrawableImageViewTarget
, Target 用 來 最 終 展 示 圖 片 的 ,buildImageViewTarget
-->ImageViewTargetFactory.buildTarget()
根據(jù)傳入 class 參數(shù)不同構(gòu)建不同的 Target 對象,這個 Class 是根據(jù)構(gòu)建 Glide 時是否調(diào)用了 asBitmap()
方法,如果調(diào)用了會構(gòu)建出BitmapImageViewTarget
,否則構(gòu)建的是GlideDrawableImageViewTarget
對象。
-->GenericRequestBuilder.into(Target)
, 該 方 法 進 行 了 構(gòu) 建 Request , 并 用RequestTracker.runRequest()
-->GenericRequest.begin()
Request request = buildRequest(target);
// 構(gòu)建 Request 對象,
target.setRequest(request);
lifecycle.addListener(target);
requestTracker.runRequest(request);
// 判斷 Glide 當(dāng)前是不是處于暫停狀態(tài)
onSizeReady()
--> `Engine.load(signature, width, height, dataFetcher, loadProvider,transformation, transcoder,priority, isMemoryCacheable, diskCacheStrategy, this)
a)先構(gòu)建
EngineKey;
b)`loadFromCache
從 緩 存 中 獲 取 EngineResource
, 如 果 緩 存 中 獲 取 到 cache 就 調(diào) 用`cb.onResourceReady(cached);
c)如果緩存中不存在調(diào)用
loadFromActiveResources從 active中獲取,如果獲取到就調(diào)用
cb.onResourceReady(cached);
d)如果 active 中也不存在,調(diào)用
EngineJob.start(EngineRunnable), 從而調(diào)用
decodeFromSource()/decodeFromCache()-->如果是調(diào) 用
decodeFromSource()-->
ImageVideoFetcher.loadData()-->
HttpUrlFetcher()調(diào) 用
HttpUrlConnection進 行 網(wǎng) 絡(luò) 請 求 資 源 --> 得 于
InputStream()后 , 調(diào) 用
decodeFromSourceData()-->
loadProvider.getSourceDecoder().decode() 方 法 解 碼-->
GifBitmapWrapperResourceDecoder.decode()-->
decodeStream()先從流中讀取 2 個字節(jié)判斷是 GIF 還是普通圖,若是 GIF 調(diào)用
decodeGifWrapper()來解碼,若是普通靜圖則調(diào)用
decodeBitmapWrapper()來解碼-->
bitmapDecoder.decode()`
1) 內(nèi)存緩存: LruResourceCache(memory)+
弱引用 activeResources
Map
<Key, WeakReference
<EngineResource
<?>>> activeResources
正在使用的資源,當(dāng) acquired變量大于 0,說明圖片正在使用,放到 activeResources
弱引用緩存中,經(jīng)過 release()
后,acquired=0,說明圖片不再使用,會把它放進 LruResourceCache
中
2)磁盤緩存: DiskLruCache
,這里分為 Source(原始圖片)和 Result(轉(zhuǎn)換后的圖片)
第一次獲取圖片,肯定網(wǎng)絡(luò)取,然后存 active\disk 中,再把圖片顯示出來,第二次讀取相同的圖片,并加載到相同大小的 imageview
中,會先從 memory 中取,沒有再去 active 中獲取。如果 activity 執(zhí)行到 onStop
時,圖片被回收,active 中的資源會被保存到memory 中,active中的資源被回收。當(dāng)再次加載圖片時,會從 memory 中取,再放入 active 中,并將 memory中對應(yīng)的資源回收。
之所以需要 activeResources
,它是一個隨時可能被回收的資源,memory 的強引用頻繁讀寫可能造成內(nèi)存激增頻繁 GC
,而造成內(nèi)存抖動。資源在使用過程中保存在 activeResources
中,而 activeResources
是弱引用,隨時被系統(tǒng)回收,不會造成內(nèi)存過多使用和泄漏。
Glide 內(nèi)存緩存最大空間(maxSize)=每個進程可用最大內(nèi)存0.4(低配手機是 每個進程可用最大內(nèi)存0.33)
磁盤緩存大小是 250MB int DEFAULT_DISK_CACHE_SIZE = 250 1024 1024;
LruCache
中 Lru
算法的實現(xiàn)就是通過 LinkedHashMap
來實現(xiàn)的。LinkedHashMap
繼承于HashMap
,它使用了一個雙向鏈表來存儲 Map 中的 Entry 順序關(guān)系,對于 get、put、remove 等操作,LinkedHashMap
除了要做 HashMap
做的事情,還做些調(diào)整 Entry 順序鏈表的工作。
LruCache
中將 LinkedHashMap
的順序設(shè)置為 LRU
順序來實現(xiàn) LRU 緩存,每次調(diào)用 get(也就是從內(nèi)存緩存中取圖片),則將該對象移到鏈表的尾端。調(diào)用 put 插入新的對象也是存儲在鏈表尾端,這樣當(dāng)內(nèi)存緩存達到設(shè)定的最大值時,將鏈表頭部的對象(近期最少用到的)移除。
當(dāng) Android 端需要獲得數(shù)據(jù)時比如獲取網(wǎng)絡(luò)中的圖片,首先從內(nèi)存中查找(按鍵查找),內(nèi)存中沒有的再從磁盤文件或 sqlite
中去查找,若磁盤中也沒有才通過網(wǎng)絡(luò)獲取
圖片加載包含封裝,解析,下載,解碼,變換,緩存,顯示等操作
免責(zé)聲明:本站發(fā)布的內(nèi)容(圖片、視頻和文字)以原創(chuàng)、轉(zhuǎn)載和分享為主,文章觀點不代表本網(wǎng)站立場,如果涉及侵權(quán)請聯(lián)系站長郵箱:is@yisu.com進行舉報,并提供相關(guān)證據(jù),一經(jīng)查實,將立刻刪除涉嫌侵權(quán)內(nèi)容。