Glide的生命周期管理
主要分為三個(gè)層次的生命周期:Activity & 網(wǎng)絡(luò) & 內(nèi)存。
我們一般認(rèn)為,應(yīng)該及時(shí)取消不必要的加載請(qǐng)求,這很耗費(fèi)資源,但在Glide這并不是必須的操作。因?yàn)?Glide 會(huì)在頁(yè)面生命周期 / 網(wǎng)絡(luò)變化時(shí),自動(dòng)取消加載或重新加載。沒(méi)錯(cuò),就是這么牛逼。
- 頁(yè)面生命周期
當(dāng)頁(yè)面不可見(jiàn)時(shí)暫停請(qǐng)求;頁(yè)面可見(jiàn)時(shí)恢復(fù)請(qǐng)求;頁(yè)面銷(xiāo)毀時(shí)銷(xiāo)毀請(qǐng)求。 - 網(wǎng)絡(luò)連接狀態(tài)
如果從 URL 加載圖片,Glide 會(huì)監(jiān)聽(tīng)設(shè)備的連接狀態(tài),并在重新連接到網(wǎng)絡(luò)時(shí)重啟之前失敗的請(qǐng)求。 - 內(nèi)存狀態(tài)
Glide 會(huì)監(jiān)聽(tīng)內(nèi)存狀態(tài),并根據(jù)不同的 level 來(lái)釋放內(nèi)存。
為什么要監(jiān)聽(tīng)頁(yè)面生命周期?
主要基于以下兩個(gè)目的: - 以確保優(yōu)先處理前臺(tái)可見(jiàn)的 Activity / Fragment,提高資源利用率;
- 在有必要時(shí)釋放資源以避免在應(yīng)用在后臺(tái)時(shí)被殺死,提高穩(wěn)定性。
三種生命周期作用域
還記得Glide使用的第一句嗎,Glide.with(參數(shù)),
with()方法可以接收Context、Activity或者Fragment類(lèi)型的參數(shù)。

先說(shuō)結(jié)論,根據(jù)傳入的參數(shù)不同,將對(duì)應(yīng)于 Application & Activity & Fragment 的作用域,具體如下:

這里不細(xì)節(jié)分析源碼實(shí)現(xiàn),我們只需要知道,不同參數(shù)通過(guò)重載方法,作用于不同的作用域
生命周期綁定
1、從 FragmentManager 中獲取 SupportRequestManagerFragment;
2、從該 Fragment 中獲取 RequestManager;
3、首次獲取,則實(shí)例化 RequestManager,后續(xù)從同一個(gè) SupportRequestManagerFragment 中都獲取的是這個(gè) RequestManager。
不拘泥于細(xì)節(jié),關(guān)鍵在于SupportRequestManagerFragment
其實(shí)就是三步走戰(zhàn)略。1.1 嘗試獲取FRAGMENT_TAG對(duì)應(yīng)的 Fragment
1.2 嘗試從臨時(shí)記錄中獲取 Fragment
-
1.3 實(shí)例化 Fragment
- 1.3.1 創(chuàng)建對(duì)象
- 1.3.2 如果父層可見(jiàn),則調(diào)用 onStart() 生命周期
- 1.3.3 臨時(shí)記錄映射關(guān)系(HashMap)
- 1.3.4 提交 Fragment 事務(wù)
- 1.3.5 post 一個(gè)消息
- 1.3.6 移除臨時(shí)記錄中的映射關(guān)系
這里具體分析一下上面這些晦澀的語(yǔ)句,注意設(shè)計(jì)的思路重點(diǎn),就是這個(gè)SupportRequestManagerFragment,這個(gè)隱藏SupportRequestManagerFragment,這個(gè)并不可見(jiàn)的SupportRequestManagerFragment。
這里為什么要添加一個(gè)隱藏的Fragment呢?
Glide并沒(méi)有辦法知道Activity的生命周期,于是Glide就使用了添加隱藏Fragment的這種小技巧,相當(dāng)于通過(guò)這個(gè)隱藏的fragment與對(duì)應(yīng)的Activity建立了聯(lián)系,因?yàn)镕ragment的生命周期和Activity是同步的,如果Activity被銷(xiāo)毀了,F(xiàn)ragment是可以監(jiān)聽(tīng)到的,這樣Glide就可以捕獲這個(gè)事件并停止圖片加載了。
這里又有一個(gè)設(shè)計(jì)點(diǎn),臨時(shí)記錄,它是為了干什么呢?
在提交 Fragment 事務(wù)之前,為什么需要先保存記錄?
這是 為了避免 SupportRequestManagerFragment 在一個(gè)作用域中重復(fù)創(chuàng)建。
因?yàn)閏ommitAllowingStateLoss()是將事務(wù) post 到消息隊(duì)列中的,也就是說(shuō),事務(wù)是異步處理的,而不是同步處理的。假設(shè)沒(méi)有臨時(shí)保存記錄,一旦在事務(wù)異步等待執(zhí)行時(shí)調(diào)用了Glide.with(...),就會(huì)在該作用域中重復(fù)創(chuàng)建 Fragment。

生命周期監(jiān)聽(tīng)
從上面的分析我們得知,Glide 為每個(gè)Activity 和 Fragment 作用域創(chuàng)建了一個(gè)無(wú)界面的 Fragment,這里我們就來(lái)分析 Glide 如何監(jiān)聽(tīng)這個(gè)無(wú)界面 Fragment 的生命周期。
首先先提到一個(gè)概念,Lifecycle,大家可以粗略的把它理解為 移動(dòng)APP頁(yè)面的狀態(tài)
其實(shí)說(shuō)起來(lái)也是三步走戰(zhàn)略,
1、在創(chuàng)建Fragment的時(shí)候會(huì)創(chuàng)建ActivityFragmentLifecycle對(duì)象;
2、在Fragment生命周期的方法中會(huì)調(diào)用Lifecycle的相關(guān)方法來(lái)通知RequestManager;
3、LifecycleListener 是一個(gè)接口,RequestManager實(shí)現(xiàn)了這個(gè)接口,Lifecycle最終是調(diào)用了lifecycleListener來(lái)通知相關(guān)的實(shí)現(xiàn)類(lèi)的,也就是RequestManager。
生命周期回調(diào)
這個(gè)就非常簡(jiǎn)單了,也就是上述的RequestManager實(shí)現(xiàn)了LifecycleListener接口后,在對(duì)應(yīng)的方法中,作出相應(yīng)的處理。
主要關(guān)注以下幾點(diǎn):
- 1、頁(yè)面不可見(jiàn)時(shí)暫停請(qǐng)求(onStop() )
- 2、頁(yè)面可見(jiàn)時(shí)恢復(fù)請(qǐng)求(onStart() )
-
3、頁(yè)面銷(xiāo)毀時(shí)銷(xiāo)毀請(qǐng)求(onDestroy() )
image.png
網(wǎng)絡(luò)連接狀態(tài)監(jiān)聽(tīng)
這個(gè)邏輯很簡(jiǎn)單,在剛才所說(shuō)的RequestManager的構(gòu)造器中,會(huì)構(gòu)建一個(gè)ConnectivityMonitor對(duì)象,它的默認(rèn)構(gòu)造工廠是DefaultConnectivityMonitorFactory,如果有網(wǎng)絡(luò)監(jiān)聽(tīng)權(quán)限,
則實(shí)例化DefaultConnectivityMonitor,在onStart()時(shí)注冊(cè)廣播監(jiān)聽(tīng)器,而在onStop()時(shí)注銷(xiāo)廣播監(jiān)聽(tīng)器。在RequestManager中根據(jù)網(wǎng)絡(luò)狀態(tài)進(jìn)行相應(yīng)的操作。
聽(tīng)起來(lái)有點(diǎn)拗口,簡(jiǎn)而言之,如果應(yīng)用有監(jiān)控網(wǎng)絡(luò)狀態(tài)的權(quán)限,那么 Glide 會(huì)監(jiān)聽(tīng)網(wǎng)絡(luò)連接狀態(tài),在頁(yè)面可見(jiàn)時(shí)注冊(cè)廣播監(jiān)聽(tīng)器,而在頁(yè)面不可見(jiàn)時(shí)注銷(xiāo)廣播監(jiān)聽(tīng)器,并在網(wǎng)絡(luò)重新連接時(shí)重新啟動(dòng)失敗的請(qǐng)求。
內(nèi)存狀態(tài)監(jiān)聽(tīng)
這個(gè)的實(shí)現(xiàn)也非常簡(jiǎn)單的的,在構(gòu)建 Glide 時(shí),會(huì)調(diào)用registerComponentCallbacks()進(jìn)行全局注冊(cè), 系統(tǒng)在內(nèi)存緊張的時(shí)候回調(diào)onTrimMemory(level)。
而 Glide 則根據(jù)系統(tǒng)內(nèi)存緊張級(jí)別(level)進(jìn)行相應(yīng)的回收,而 RequestManager 在 TRIM_MEMORY_MODERATE 級(jí)別會(huì)暫停請(qǐng)求。
