如何在DefaultLifecycleObserver中实现onDestroyView逻辑
问题
当前使用的实现代码如下:
class AutoClearedValue<T : Any>(val fragment: Fragment) : ReadWriteProperty<Fragment, T> { private var _value: T? = null init { fragment.lifecycle.addObserver(object: DefaultLifecycleObserver { override fun onCreate(owner: LifecycleOwner) { fragment.viewLifecycleOwnerLiveData.observe(fragment) { viewLifecycleOwner -> viewLifecycleOwner?.lifecycle?.addObserver(object: DefaultLifecycleObserver { override fun onDestroy(owner: LifecycleOwner) { _value = null } }) } } }) } override fun getValue(thisRef: Fragment, property: KProperty<*>): T { return _value ?: throw IllegalStateException( "should never call auto-cleared-value get when it might not be available" ) } override fun setValue(thisRef: Fragment, property: KProperty<*>, value: T) { _value = value } } /** * Creates an [AutoClearedValue] associated with this fragment. */ fun <T : Any> Fragment.autoCleared() = AutoClearedValue<T>(this)
需求是在onDestroyView(视图销毁)生命周期节点将存储值(比如ViewBinding实例)置空,原本预期置空逻辑应该写在onDestroyView回调中:
override fun onDestroyView(owner: LifecycleOwner) { super.onDestroyView(owner) _value = null }
但当前实现仅重写了onDestroy方法执行置空,同时发现DefaultLifecycleObserver中不存在onDestroyView方法,无法直接重写,需要实现视图销毁时自动清空值的效果。
解答
首先明确一个核心概念:DefaultLifecycleObserver里没有onDestroyView是正常设计——onDestroyView不属于Fragment自身的生命周期回调,而是Fragment *视图生命周期(ViewLifecycleOwner)*的回调,两个生命周期是完全分离的。
你现在代码里给viewLifecycleOwner.lifecycle添加的Observer中重写的onDestroy,触发时机正好对应Fragment的onDestroyView节点,不是你误以为的Fragment实例销毁的onDestroy时机,这部分逻辑的触发时机其实是对的。
不过现有实现有几个可以优化的点,修正后可以更稳定地满足需求:
- 不需要等Fragment自身的
onCreate回调才去监听viewLifecycleOwnerLiveData,初始化时直接监听即可 - 每次视图生命周期所有者更新时,先手动清空一次旧值,避免旧视图实例泄漏
- 移除多余的非空判断,
viewLifecycleOwnerLiveData返回的非空值才是有效生命周期所有者
修正后的完整实现如下:
class AutoClearedValue<T : Any>(val fragment: Fragment) : ReadWriteProperty<Fragment, T> { private var _value: T? = null init { fragment.viewLifecycleOwnerLiveData.observe(fragment) { viewLifecycleOwner -> // 新视图创建前先清空旧值,避免泄漏 _value = null viewLifecycleOwner.lifecycle.addObserver(object : DefaultLifecycleObserver { // 此处onDestroy对应视图生命周期销毁,即onDestroyView触发时机 override fun onDestroy(owner: LifecycleOwner) { _value = null } }) } } override fun getValue(thisRef: Fragment, property: KProperty<*>): T { return _value ?: throw IllegalStateException( "禁止在视图销毁后访问AutoClearedValue存储的实例" ) } override fun setValue(thisRef: Fragment, property: KProperty<*>, value: T) { _value = value } } fun <T : Any> Fragment.autoCleared() = AutoClearedValue<T>(this)
如果觉得onDestroy的命名容易和Fragment实例销毁的回调混淆,也可以换用LifecycleEventObserver明确监听视图生命周期的销毁事件,效果完全一致:
viewLifecycleOwner.lifecycle.addObserver { _, event -> if (event == Lifecycle.Event.ON_DESTROY) { _value = null } }
内容的提问来源于stack exchange,提问作者c-an
相关产品推荐
相关产品推荐

