持续创作,加速成长!这是我参与「掘金日新计划 · 6 月更文挑战」的第5天,点击查看活动详情
本篇文章主要是分析下
LeakCanary
如何监听Fragment、Fragment View、ViewModel
销毁时机的,至于老话常谈的Activity
销毁监听大家都知道,就不在此过于阐述了。
添加依赖,基于最新版本分析
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
销毁监听都能监听得到:
- 监听
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
销毁时机的,下篇文章再见!!