Glide4.10 加載網絡圖片的基本流程
Glide.with(context).load(url).into(imageView);
加載一張圖片,主要經過上面三個步驟; 下面會逐個分析三個步驟;
本文針對的Glide 4.10版本;
第1步:with(context)
生成RequestManager對象
- 根據context是否是Application,Glide決定是否需要關注頁面的生命週期;
- Glide通過添加一個空Fragment的方式感知生命週期變化;
第2步:load(url)
生成RequestManager對象
- 大部分api在這個階段添加到RequestManager, 比如
listener()
; - 該階段指定了model類型,本例中model是String類型的url;
第3步:into(imageView)
- 首先,使用imageView構造Target,
into()
主要任務:創建並且執行 Request:requestManager.track(target, request);
- 隨後,執行Request的
begin()
方法, 本例爲SingleRequest對象的begin()
; - 執行Target的
getSize()
指定所需寬高;此時自定義Target可以設置想要的寬高; - 最後,執行SingleRequest的
onSizeReady()
, 調用Engine對象的load()
方法開始加載;
第3.1步驟: Engine.load()
加載圖片
- 首先試圖從內存緩存(內存緩存分兩級)中取,
loadFromMemory()
步驟:loadFromActiveResources()
:根據Key從ActivieResources集合獲取;- ActivieResources爲1級內存緩存,存儲當前Activity正在使用的資源;
loadFromCache()
:再從MemoryCache中獲取;- MemoryCache爲2級內存緩存,該接口的實現類爲LruResourceCache;
- 如果
loadFromMemory()
沒獲取到緩存Resource,則從文件緩存或者數據源獲取; - Engine對象
waitForExistingOrStartNewJob()
創建EngineJob和DecodeJob;- EngineJob是從
Pools.Pool<EngineJob<?>> pool
對象池獲取;DecodeJob類似; - DecodeJob繼承自Runnable;EngineJob會啓動DecodeJob;
- EngineJob是從
- DecodeJob的
run()
方法,核心邏輯在DecodeJob的runWrapped()
方法; runWrapped()
方法,主要通過狀態機runReason控制;- 首先將狀態機runReason初始爲
RunReason.INITIALIZE
; - 執行
getNextGenerator()
獲取DataFetcherGenerator;- DataFetcherGenerator接口用來獲取數據,它有三個具體實現類:
- ResourceCacheGenerator:獲取downsampled/transformed的資源數據;
- DataCacheGenerator:獲取原始未修改過的資源數據;
- SourceGenerator:意味着從原始數據源獲取數據;
- 依次查詢上面3個實現類;本例爲第一次獲取圖片情形,currentGenerator最終爲SourceGenerator,即需要從Source中取數據;
- DataFetcherGenerator接口用來獲取數據,它有三個具體實現類:
- 執行currentGenerator的
startNext()
,核心邏輯:尋找合適的LoadData,進而生成Fetcher,執行Fetcher的loadData()
方法獲取InputStream;- 從ModelLoader集合中尋找合適的ModelLoader,依據是
boolean handles(Model)
, 該方法返回true表示可以處理該Model;- Glide對象初始化時註冊所有ModelLoader,將其存儲在Registry對象中;
- ModelLoader列表可以通過GlideContext獲取;
- 本例爲加載網絡圖片,Loader爲HttpUriLoader,因爲它的
handles()
方法是判斷scheme是否爲http或https;
- Glide對象初始化時註冊所有ModelLoader,將其存儲在Registry對象中;
- HttpUriLoader的model是Uri類型,它將model包裝爲GlideUrl類型,將load工作交給HttpGlideUrlLoader的
buildLoadData()
; - HttpGlideUrlLoader的
buildLoadData()
創建用於網絡通信的HttpUrlFetcher對象;網絡通信的結果是InputStream, 隨後需要將其decode爲Resource; - fetcher拿到IS後,回調DecodeJob的
onDataFetcherReady(Key, Resource ...)
;
- 從ModelLoader集合中尋找合適的ModelLoader,依據是
- DecodeJob通過回調拿到fetcher,執行
decodeFromRetrievedData()
解碼,拿到Resource對象;- 執行
decodeFromData()
獲取Resource, 具體邏輯在decodeFromFetcher()
:decodeHelper.getLoadPath()
獲取LoadPath;- 首先通過
getDecodePaths()
獲取DecodePath列表;- DecodePath和ModelLoader類似,都是註冊在Registry,也是通過
handles()
方法判斷;
- DecodePath和ModelLoader類似,都是註冊在Registry,也是通過
- 本例的DecodePath列表中只包含ByteBufferBitmapDecoder;
- 使用DecodePath列表創建並返回一個LoadPath:
- 首先通過
- 執行LoadPath的
runLoadPath()
方法:返回Resource;- 遍歷DecodePath列表,調用
DecodePath.decodeResource()
進行解碼; - 解碼完成後,回調DecodeJob的
onResourceDecoded()
, 執行Transform、緩存等操作; - 本例Resource爲Bitmap, 實際上Bitmap/Drawable/Gif等都實現Resource接口;
- 遍歷DecodePath列表,調用
- 拿到Resource後,調用DecodeJob的
notifyEncodeAndRelease()
; - 回調EngineJob的
onResourceReady(Resource)
,進一步執行notifyCallbacksOfResult()
:- 回調Engine的
onEngineJobComplete()
,將Resource保存到內存緩存中; - 回調SingleRequest的
onResourceReady()
: 回調listener(new RequestListener)
中邏輯;
- 回調Engine的
- 執行
- SingleRequest回調Target的同名方法
onResourceReady()
,完成最終的顯示;- 本例執行
into(ImageView)
,則會執行ImageViewTarget的onResourceReady()
; - ImageViewTarget的
onResourceReady()
調用抽象方法setResource(Resource)
,如果執行過asBitmap()
, 便執行BitmapImageViewTarget的setResource()
,具體爲view.setImageBitmap(resource)
;
- 本例執行
- 此時圖片便加載出來了;