持续创作,加速成长!这是我参与「掘金日新计划 · 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销毁时机的,下篇文章再见!!