Glide的一點(diǎn)收獲

1、Glide,with()方法的重載種類非常多,既可以傳入Activity,也可以傳入Fragment或者是Context。每一個(gè)with()方法重載的代碼都非常簡(jiǎn)單,都是先調(diào)用RequestManagerRetriever的靜態(tài)get()方法得到一個(gè)RequestManagerRetriever對(duì)象,這個(gè)靜態(tài)get()方法就是一個(gè)單例實(shí)現(xiàn),沒(méi)什么需要解釋的。然后再調(diào)用RequestManagerRetriever的實(shí)例get()方法,去獲取RequestManager對(duì)象。

RequestManagerRetriever類中看似有很多個(gè)get()方法的重載,什么Context參數(shù),Activity參數(shù),F(xiàn)ragment參數(shù)等等,實(shí)際上只有兩種情況而已,即傳入Application類型的參數(shù),和傳入非Application類型的參數(shù)。

我們先來(lái)看傳入Application參數(shù)的情況。如果在Glide.with()方法中傳入的是一個(gè)Application對(duì)象,那么這里就會(huì)調(diào)用帶有Context參數(shù)的get()方法重載,然后會(huì)在第44行調(diào)用getApplicationManager()方法來(lái)獲取一個(gè)RequestManager對(duì)象。其實(shí)這是最簡(jiǎn)單的一種情況,因?yàn)锳pplication對(duì)象的生命周期即應(yīng)用程序的生命周期,因此Glide并不需要做什么特殊的處理,它自動(dòng)就是和應(yīng)用程序的生命周期是同步的,如果應(yīng)用程序關(guān)閉的話,Glide的加載也會(huì)同時(shí)終止。

接下來(lái)我們看傳入非Application參數(shù)的情況。不管你在Glide.with()方法中傳入的是Activity、FragmentActivity、v4包下的Fragment、還是app包下的Fragment,最終的流程都是一樣的,那就是會(huì)向當(dāng)前的Activity當(dāng)中添加一個(gè)隱藏的Fragment。具體添加的邏輯是在上述代碼的第117行和第141行,分別對(duì)應(yīng)的app包和v4包下的兩種Fragment的情況。那么這里為什么要添加一個(gè)隱藏的Fragment呢?因?yàn)镚lide需要知道加載的生命周期。很簡(jiǎn)單的一個(gè)道理,如果你在某個(gè)Activity上正在加載著一張圖片,結(jié)果圖片還沒(méi)加載出來(lái),Activity就被用戶關(guān)掉了,那么圖片還應(yīng)該繼續(xù)加載嗎?當(dāng)然不應(yīng)該??墒荊lide并沒(méi)有辦法知道Activity的生命周期,于是Glide就使用了添加隱藏Fragment的這種小技巧,因?yàn)镕ragment的生命周期和Activity是同步的,如果Activity被銷(xiāo)毀了,F(xiàn)ragment是可以監(jiān)聽(tīng)到的,這樣Glide就可以捕獲這個(gè)事件并停止圖片加載了。

這里額外再提一句,從第48行代碼可以看出,如果我們是在非主線程當(dāng)中使用的Glide,那么不管你是傳入的Activity還是Fragment,都會(huì)被強(qiáng)制當(dāng)成Application來(lái)處理。不過(guò)其實(shí)這就屬于是在分析代碼的細(xì)節(jié)了,本篇文章我們將會(huì)把目光主要放在Glide的主線工作流程上面,后面不會(huì)過(guò)多去分析這些細(xì)節(jié)方面的內(nèi)容。

總體來(lái)說(shuō),第一個(gè)with()方法的源碼還是比較好理解的。其實(shí)就是為了得到一個(gè)RequestManager對(duì)象而已,然后Glide會(huì)根據(jù)我們傳入with()方法的參數(shù)來(lái)確定圖片加載的生命周期,并沒(méi)有什么特別復(fù)雜的邏輯。

2、load()

那么我們先來(lái)看load()方法,這個(gè)方法中的邏輯是非常簡(jiǎn)單的,只有一行代碼,就是先調(diào)用了fromString()方法,再調(diào)用load()方法,然后把傳入的圖片URL地址傳進(jìn)去。而fromString()方法也極為簡(jiǎn)單,就是調(diào)用了loadGeneric()方法,并且指定參數(shù)為String.class,因?yàn)閘oad()方法傳入的是一個(gè)字符串參數(shù)。那么看上去,好像主要的工作都是在loadGeneric()方法中進(jìn)行的了。

其實(shí)loadGeneric()方法也沒(méi)幾行代碼,這里分別調(diào)用了Glide.buildStreamModelLoader()方法和Glide.buildFileDescriptorModelLoader()方法來(lái)獲得ModelLoader對(duì)象。ModelLoader對(duì)象是用于加載圖片的,而我們給load()方法傳入不同類型的參數(shù),這里也會(huì)得到不同的ModelLoader對(duì)象。不過(guò)buildStreamModelLoader()方法內(nèi)部的邏輯還是蠻復(fù)雜的,這里就不展開(kāi)介紹了,要不然篇幅實(shí)在收不住,感興趣的話你可以自己研究。由于我們剛才傳入的參數(shù)是String.class,因此最終得到的是StreamStringLoader對(duì)象,它是實(shí)現(xiàn)了ModelLoader接口的。

最后我們可以看到,loadGeneric()方法是要返回一個(gè)DrawableTypeRequest對(duì)象的,因此在loadGeneric()方法的最后又去new了一個(gè)DrawableTypeRequest對(duì)象,然后把剛才獲得的ModelLoader對(duì)象,還有一大堆雜七雜八的東西都傳了進(jìn)去。具體每個(gè)參數(shù)的含義和作用就不解釋了,我們只看主線流程。

3、load()方法中的代碼雖然有點(diǎn)長(zhǎng),但大多數(shù)的代碼都是在處理緩存的。關(guān)于緩存的內(nèi)容我們會(huì)在下一篇文章當(dāng)中學(xué)習(xí),現(xiàn)在只需要從第45行看起就行。這里構(gòu)建了一個(gè)EngineJob,它的主要作用就是用來(lái)開(kāi)啟線程的,為后面的異步加載圖片做準(zhǔn)備。接下來(lái)第46行創(chuàng)建了一個(gè)DecodeJob對(duì)象,從名字上來(lái)看,它好像是用來(lái)對(duì)圖片進(jìn)行解碼的,但實(shí)際上它的任務(wù)十分繁重,待會(huì)我們就知道了。繼續(xù)往下看,第48行創(chuàng)建了一個(gè)EngineRunnable對(duì)象,并且在51行調(diào)用了EngineJob的start()方法來(lái)運(yùn)行EngineRunnable對(duì)象,這實(shí)際上就是讓EngineRunnable的run()方法在子線程當(dāng)中執(zhí)行了。

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

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

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