LeakCanary如何監聽Fragment、Fragment View、ViewModel銷燬時機?
theme: juejin highlight: a11y-light
持續創作,加速成長!這是我參與「掘金日新計劃 · 6 月更文挑戰」的第5天,點擊查看活動詳情
本篇文章主要是分析下
LeakCanary
如何監聽Fragment、Fragment View、ViewModel
銷燬時機的,至於老話常談的Activity
銷燬監聽大家都知道,就不在此過於闡述了。
添加依賴,基於最新版本分析
groovy
dependencies {
debugImplementation 'com.squareup.leakcanary:leakcanary-android:2.9.1'
}
前置知識
LeakCanary
是藉助ContentProvider
來實現自動初始化的:
我們可以通過顯示在xml中設置leak_canary_watcher_auto_install
為false
來關閉其自動初始化。
- 在
ContentProvider
的onCreate()
方法會調用AppWatcher.manualInstall()
,看下這個方法:
我們要關注的就是watchersToInstall
這個參數,這個參數默認使用appDefaultWatchers()
方法進行賦值,走進去看下:
這個裏面就返回了監聽Activity、Service、Root View、Fragment、ViewModel
要用到的監聽對象,看到類名就能知曉它是用來監聽什麼對象銷燬的,接下來我們來一個個的進行分析(除了ActivityWatcher
)。
監聽Fragment
銷燬時機
這個使用到的就是FragmentAndViewModelWatcher
這個對象實現的,看下里面源碼:
- 如果當前
SDK
版本是8.0及以上就添加AndroidOFragmentDestroyWatcher
監聽Fragment
銷燬時機; - 如果當前是
Androidx
版本的Fragment
,就添加AndroidXFragmentDestroyWatcher
監聽銷燬; - 如果是
supoort
下的Fragment
,就添加AndroidSupportFragmentDestroyWatcher
監聽銷燬;
PS:這個地方使用了一個小技巧,如何分別兼容
androidx
和support
下的Fragment
監聽:分別嘗試去反射
androidx
下的androidx.fragment.app.Fragment
和support
下的android.support.v4.app.Fragment
,反射失敗了就代表不存在當前的包名路徑,就不會添加對應的監聽,反之就添加對應監聽。
這個地方我們就看下AndroidXFragmentDestroyWatcher
如何監聽銷燬Fragment
的:
創建了一個
FragmentManager.FragmentLifecycleCallbacks
的子類,這個裏面就有我們非常熟悉的監聽Fragment
生命週期的方法。
我們要監聽的是Fragment
的銷燬時機,那就直接重寫onFragmentDestroyed
方法,將該Fragment
對象添加泄漏觀察:
除此之外,我們還發現重寫了onFragmentViewDestroyed
方法,這就説明還可以監聽Fragment
的View
是否發生了內存泄漏。畢竟,Fragment
中View
生命週期和Fragment
生命週期不一定是同步的。
最終我們將這個自定義的FragmentManager.FragmentLifecycleCallbacks
的子類對象添加到Activity
的FragmentManager
中從而實現監聽:
監聽ViewModel
銷燬時機
實現ViewModel
監聽的類也是FragmentAndViewModelWatcher
,Activity
和Fragment
中的ViewModel
銷燬監聽都能監聽得到:
1. 監聽Fragment
中ViewModel
銷燬的監聽類的注入時機就是發生在上面一節自定義FragmentManager.FragmentLifecycleCallbacks
中onFragmentCreated
方法中:
- 監聽
Activity
中ViewModel
銷燬的監聽類的注入時機是在調用registerFragmentLifecycleCallbacks
注入Fragment
生命週期監聽的同一處:
可以發現最終都會調用ViewModelClearedWatcher
類實現監聽,只不過Activity
和Fragment
各自傳入的ViewModelStore
不同。
PS:
ViewModelStore
裏面有一個HashMap<String, ViewModel>
類型的map對象保存ViewModel
看下ViewModelClearedWatcher
這個類:
它繼承了ViewModel
這個類,並且將該類注入到了Activity
和Fragment
對應的ViewModelStore
中:
PS: 由於需要創建帶構造參數的
ViewModel
,所以需要自定義一個Factory
實現構造參數的注入
然後重寫了onClear()
方法:
在該方法中,反射獲取ViewModelStore
中的mMap集合中保存的所有ViewModel
,而onClear()
方法只有在Activity
或Fragment
非因配置的更改發生的銷燬中被執行,所以當onClear()
執行時,就代表Activity
和Fragment
要銷燬了,自然能裏面的所有ViewModel
應該要被銷燬了,依次添加到內存泄漏的監聽中。
到了這裏大家應該明白了,LeakCannary
通過向Activity
或Fragment
的ViewModelStore
注入一個自定義的ViewModel
並監聽其onClear()
的執行時機,從而實現監聽Activity
或Fragment
中所有ViewModel
的銷燬時機,並添加到內存泄漏監聽中。
最後
還會有一篇文章來分析LeakCanary
如何實現Root View
、Service
銷燬時機的,下篇文章再見!!
- kotlin密封sealed class/interface的迭代之旅
- 2022年12月12日—2022年12月25日Android精品文章一覽
- Sqlite簡易性能優化方案,給你的應用插上“翅膀”
- 築基篇:設置界面的開發利器Preference Library,瞭解一下~
- Android消息機制完整的執行流程,瞭解一下
- 你可能需要了解下的Android開發技巧(二)
- 超有用的Android開發技巧:攔截界面View創建
- Handler創建的幾個必備知識點,瞭解一下
- Android消息機制中Message常用的幾種監控方式
- 數見不鮮的RecyclerView使用技巧,你瞭解嗎(一)?
- 常用到的幾個Kotlin開發技巧,減少對業務層代碼的入侵
- 超好用的官方core-ktx庫,瞭解一下(終)~
- Take a look,從delay()方法看協程的掛起與恢復
- 超好用的官方core-ktx庫,瞭解一下~
- 官方core-ktx庫能對SparseArray系列、Pair開發帶來哪些便利?
- 官方core-ktx庫能對富文本Span開發帶來哪些便利2
- 你需要了解的官方core-ktx庫能對開發帶來哪些便利1
- LeakCanary如何監聽Fragment、Fragment View、ViewModel銷燬時機?
- 非反射動態設置TabLayout指示器的寬度
- 探究EventBus粘性事件實現機制