文章目录转载请标明出处:http://blog.csdn.net/zhaoyanjun6/article/details/125585064
本文出自【赵彦军的博客】
- ViewTreeLifecycleOwner是什么?
- 实现原理?
- ComponentActivity
- Fragment
- DialogFragment
- ComponentDialog
- Fragment 作为 LifecycleOwner 遇到的坑
- onCreate
- onViewCreated
- getViewLifecycleOwnerLiveData
- lifecycleScope
- 总结
ViewTreeLifecycleOwner 是Lifecycle KTX中提供的View的一个扩展方法,可以快速地获取一个最近的Fragment或者Activity的LifecycleOwner。
view.findViewTreeLifecycleOwner()实现原理? ComponentActivity
通过 ViewTreeLifecycleOwner.set 将当前 lifecycle 设置到decorView
通过 ViewTreeLifecycleOwner.set 将当前 lifecycle 设置到根view
DialogFragment通过 ViewTreeLifecycleOwner.set 将当前 lifecycle 设置到decorView
ComponentDialog通过 ViewTreeLifecycleOwner.set 将当前 lifecycle 设置到decorView
在 Fragment 的 onCreate 用 this 做 LifecycleOwner 没有问题。
class MyFragment : Fragment() {
private val viewModel by activityViewModels()
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
viewModel.some.observe(this) { }
}
}
因为在 Fragment Destory 会自动移除监听。
onViewCreated那么我们在 onViewCreated 还能使用上面的监听代码吗?
试试看
class MyFragment : Fragment() {
private val viewModel by activityViewModels()
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。
相关文章:Jetpack 易错分享:还在使用 Fragment 作为 LifecycleOwner ?
总结随着 MVVM 的普及,我们可能需要在View 内部基于lifecycle 进行livedata 订阅等工作,当View嵌套比较深时,使用ViewTreeLifecycleOwner扩展方法可以避免lifecycle的层层传递,简化代码.



