You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何在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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.26 14:33:29