Android Glide(二)生命周期感知

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ù)。


image.png

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


image.png

這里不細(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。


image.png

生命周期監(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)求。

?著作權(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)容