本文出自【赵彦军的博客】
文章目录
- ViewTreeLifecycleOwner是什么?
- 实现原理?
- ComponentActivity
- Fragment
- DialogFragment
- ComponentDialog
- Fragment 作为 LifecycleOwner 遇到的坑
- onCreate
- onViewCreated
- getViewLifecycleOwnerLiveData
- lifecycleScope
- 总结
ViewTreeLifecycleOwner是什么?
ViewTreeLifecycleOwner 是Lifecycle KTX中提供的View的一个扩展方法,可以快速地获取一个最近的Fragment或者Activity的LifecycleOwner。
view.findViewTreeLifecycleOwner()

实现原理?
ComponentActivity
通过 ViewTreeLifecycleOwner.set 将当前 lifecycle 设置到decorView

Fragment
通过 ViewTreeLifecycleOwner.set 将当前 lifecycle 设置到根view

DialogFragment
通过 ViewTreeLifecycleOwner.set 将当前 lifecycle 设置到decorView

ComponentDialog
通过 ViewTreeLifecycleOwner.set 将当前 lifecycle 设置到decorView

Fragment 作为 LifecycleOwner 遇到的坑
onCreate
在 Fragment 的 onCreate 用 this 做 LifecycleOwner 没有问题。
class MyFragment : Fragment() {
private val viewModel by activityViewModels<MyViewModel>()
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
viewModel.some.observe(this) { }
}
}因为在 Fragment Destory 会自动移除监听。
onViewCreated
那么我们在 onViewCreated 还能使用上面的监听代码吗?
试试看
class MyFragment : Fragment() {
private val viewModel by activityViewModels<MyViewModel>()
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
super.onViewCreated(view, savedInstanceState)
viewModel.some.observe(this) {
Log.d("yu--", "some $it")
}
}
}这就行了? 等等,会报错

意思是,这里的 LifecyclerOwner 要使用 viewLifecyclerOwner , 代码如下:

为什么会报错?
LiveData 之所以能够防止泄露,是当 LifecycleOwner 生命周期走到 DESTROYED 的时候会 remove 调其关联的 Observer。

是由于 Fragment 的 Lifecycle 与 Fragment#mView 的 Lifecycle 不一致导致我们订阅 LiveData 的时机和所使用的 LivecycleOwner 不匹配

明白了问题原因,解决思路也就清楚了:必须要保证订阅的时机和所使用的 LifecycleOwner相匹配,即要么调整订阅时机,要么修改LifecycleOwner。
getViewLifecycleOwnerLiveData
顺道提一下,与 getViewLifecycleOwner 同时新增的还有 getViewLifecycleOwnerLiveData。从前面贴的源码中对 mViewLifecycleOwnerLiveData 的使用,应该可以猜出它的作用:它是前文讨论的思路1的实现方案,即使在 onCreate 中订阅,由于在 onCreateView 中对 LiveData 进行了重新设置,所以重建后的 View 也可以更新数据。
// Then inform any Observers of the new LifecycleOwner
mViewLifecycleOwnerLiveData.setValue(mViewLifecycleOwner);
需要特别注意的是,根据 MVVM 最佳实践,我们希望由 ViewModel 而不是 Fragment 持有 LiveData,所以不再推荐使用 getViewLifecycleOwnerLiveData。
lifecycleScope
前面都是以 LiveData 为例介绍对 ViewLifecycleOwner 的使用, 如今大家也越来越多的开始使用协程的 StateFlow , 同样要注意不要错用 LifecycleOwner。
订阅 StateFlow 需要 CoroutineScope, AndroidX 提供了基于 LifecycleOwner 的扩展方法。
val LifecycleOwner.lifecycleScope: LifecycleCoroutineScope
get() = lifecycle.coroutineScope
当我们在 Fragment 中获取 lifecycleScope 时,切记要使用 ViewLifecycleOwner。

总结
随着 MVVM 的普及,我们可能需要在View 内部基于lifecycle 进行livedata 订阅等工作,当View嵌套比较深时,使用ViewTreeLifecycleOwner扩展方法可以避免lifecycle的层层传递,简化代码.









