【问题标题】:Why Observers added as observeForever to LiveData must be removed?为什么必须删除作为 observeForever 添加到 LiveData 的观察者?
【发布时间】:2019-09-18 11:34:18
【问题描述】:

我在Android LiveData documentation 上看到:

您可以使用 observeForever(Observer) 方法注册没有关联 LifecycleOwner 对象的观察者。在这种情况下,观察者被认为始终处于活动状态,因此始终会收到有关修改的通知。您可以调用 removeObserver(Observer) 方法删除这些观察者。

我正在使用 ViewModel 并在我的 ViewModel 类中声明 LiveDatas 并使用 MVVM 架构模式构建应用程序。在我的 viewModel 中,我将 observeForever 设置为 LiveData:

val password by lazy {
    MutableLiveData<String>()
}

init {
    initObservable()
}

private fun initObservable() {
    password.observeForever {
        ...
    }
}

根据我从文档中了解到的情况,每次实例化 ViewModel(使用前面的代码)的视图被破坏时,我都应该删除观察者,对吗?但是一旦视图被销毁,Observers不应该被销毁吗(因为ViewModel实例在视图中被实例化并且也会被销毁)?

【问题讨论】:

  • 你是如何获得这个ViewModel实例的?为什么从ViewModel 本身内部观察到password

标签: android android-livedata android-viewmodel android-mvvm


【解决方案1】:

“每次实例化 ViewModel(使用前面的代码)的视图被破坏时,我都应该移除观察者,对吗?”

如果您在 ViewModel 中使用 observeForever(observer) 观察 LiveData

  • 您不必担心 View 的生命周期,因为它与 ViewModel 的生命周期不同。 ViewModel 应该能够比创建它的 View 活得更久。相反,当不需要 ViewModel 时,框架将调用 onCleared(),因此您应该在此处处理删除观察者。

如果您使用observe(lifecyclerowner, observer)视图中观察LiveData

  • 当生命周期所有者被销毁时,框架会自动移除观察者。


“但是一旦视图被销毁,Observers不应该被销毁吗(因为ViewModel实例在视图中被实例化并且也会被销毁)?”

这个问题更像是一个 Java 问题而不是 Android。

想想“被摧毁”是什么意思。当一个 View 或 ViewModel 被 Android Framework 销毁时,并不意味着该对象完全从内存中移除。只要有其他对象(例如observer)引用它们,您的活动和片段就不会被垃圾回收。

如果你调用observe(activity, observer),那么Android Framework可以跟踪activity实例和observer实例之间的连接,因此它可以在它想要杀死activity时杀死observer。但是,如果您只是调用observeForever(observer),Android 框架根本无法判断该观察者属于哪个对象。

【讨论】:

    【解决方案2】:

    ViewModel 中实现 Sanlok Lee 的答案,它看起来像这样:

    val password by lazy {
        MutableLiveData<String>()
    }
    
    private val passwordObserver = Observer<String> {
        ...
    }
    
    init {
        initObservable()
    }
    
    private fun initObservable() {
        password.observeForever(passwordObserver)
    }
    
    override fun onCleared() {
        password.removeObserver(passwordObserver)
        super.onCleared()
    }
    

    【讨论】:

      【解决方案3】:

      根据我对文档的理解,我应该删除 每次实例化 ViewModel 的视图时的观察者

      要实现这一点,您应该在视图(活动、片段)中实例化您的视图模型并像这样观察实时数据

      val model = ViewModelProviders.of(this).get(MyViewModel::class.java)
              model.getUsers().observe(this, Observer<List<User>>{ users ->
                  // update UI
              })
      

      通过传递this,您将观察livedata 绑定到view's 生命周期,因此当视图(活动、片段)将被销毁时,视图模型和观察者都将被销毁。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2018-10-18
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多