数据绑定是否会从实现 Observable 的 ViewModel 取消注册监听器?

Will data binding unregister listeners from a ViewModel implementing Observable?

对于我的 ViewModel 向 UI 提供的数据,我有一些更复杂的逻辑,因此仅通过 LiveData 公开数据对我来说是行不通的。现在我在 Android docs 中看到我可以在我的 ViewModel 上实施 Observable 以获得我需要的细粒度控制。

但是在文档中它还说:

There are situations where you might prefer to use a ViewModel component that implements the Observable interface over using LiveData objects, even if you lose the lifecycle management capabilities of LiveData.

内置的 Android 数据绑定有多智能?它会在必要时自动取消注册它的侦听器吗(例如,在 View 被破坏的配置更改时),这样我就不必关心丢失的生命周期功能?或者我是否必须观看视图的生命周期并取消注册它的听众? (=手动执行 LiveData 通常为我执行的操作)。

没有。 ViewModel 不会自动注销 Observable 订阅。你可以手动完成。很简单。

  • 首先你创建CompositeDisposable
    protected var disposables = CompositeDisposable()
  • 其次,创建您的 Observable(可能是一些请求或 UI 事件侦听器)订阅它并将其结果分配给 CompositeDisposable
    disposables.add(
        someObservable
            .subscribeOn(Schedulers.io())
            .observeOn(AndroidSchedulers.mainThread())
            .subscribe({ data ->
                // update UI or some ObservableFields for view/databinding
            }, { exception ->
                // handle errors here
            })
    )
  • 你应该做的最后一件事是像这样覆盖 ViewModel 的方法 onCleared()
    override fun onCleared() {
        super.onCleared()
        disposables.clear()
    }

这样所有添加到您的 CompositeDisposable 的订阅都会被自动清除

编辑

我只展示了例子。您也可以在 onConfigurationChanged 或 onCreate 或 onResume 中添加触发器以清除订阅 - 但它取决于应用程序的特定用例。我只给了一个一般的。

希望对您有所帮助。

DataBinding 不会为您取消注册。它只是帮助绑定您的布局文件和 ViewModel。 viewModel 将保护您免受设备配置更改的影响。您仍然需要在您的基础 activity 或片段中应用 onSavedViewState() ,因为 viewModel 没有涵盖这一点。根据取消注册,LiveData 会这样做。

@Pavio 已经教过你如何创建 Observable,这就是 RxJava 的工作方式。我建议将 kotlin 的协程和 viewModel 与 LiveData 一起使用,以充分利用您的情况。 Rx 有一个学习曲线,尽管它确实为各种操作提供了数百个操作符。如果您真的想学习 kotlin 方式,请查看 kotlin flows and channels。

如果我处在你的位置,我会用 ViewModels、LiveData 和 Coroutines 解决我的问题。

How intelligent is the built-in Android data binding? Will it automatically unregister it's listeners when necessary (e.g. on configuration changes where the View is destroyey) so that I don't have to care about the lost lifecycle capabilities? Or do I have to watch the Lifecycle of the View and unregister it's listeners? (=do manually what LiveData normally does for me).

所以我做了一些测试。我在我的 ViewModel 上实施了 androidx.databinding.Observable 并使用以下日志调用进行了配置更改:

override fun removeOnPropertyChangedCallback(
    callback: androidx.databinding.Observable.OnPropertyChangedCallback?) {
    Log.d("APP:EVENTS", "removeOnPropertyChangedCallback " + callback.toString())
}

override fun addOnPropertyChangedCallback(
    callback: androidx.databinding.Observable.OnPropertyChangedCallback?) {
    Log.d("APP:EVENTS", "addOnPropertyChangedCallback " + callback.toString())
}

我看到每次在布局绑定表达式中引用我的视图模型时都会调用 addOnPropertyChangedCallback。我一次也没有看到 removeOnPropertyChangedCallback 被调用。我的初步结论是 AndroidX 数据绑定是愚蠢的,不会自动删除侦听器。
仅供参考: 回调类型是 ViewDataBinding.WeakPropertyListener

但是,我偷看了ViewDataBinding.java source code and found that it is using Weak References添加监听器。

所以这意味着,在配置更改时,Android OS 应该能够对您的 Activity/Fragment 进行垃圾回收,因为视图模型没有强引用。

我的建议:不要添加样板来注销侦听器。 Android 不会在配置更改时泄漏对您的活动和片段的引用

现在,如果您选择不使用 LiveData,请考虑让您的视图模型实现 LifecycleObserver,这样当您的 Activity/Fragment 进入活动状态。这是您因不使用 LiveData 而失去的关键行为。否则,您可以使用您在其他时间共享的文档中提到的 PropertyChangeRegistry.notifyCallbacks() 发出通知。不幸的是,我认为这只能用于通知 all 属性。

另一件事...虽然我没有验证行为,但源代码似乎表明弱引用用于 ObservableFieldObservableListObservableMap 等。

LiveData 之所以不同,有以下几个原因:

  1. The documentation for LiveData.observe 表示在生命周期所有者被销毁之前,对观察者和生命周期所有者都有一个强引用。
  2. LiveData 发出的信号与 ObservableField 不同。 LiveData 将在调用 setValuepostValue 时发出,而不考虑值是否实际更改。 ObservableField 并非如此。出于这个原因,LiveData 可以通过多次设置相同的值来发送有点 "pseudo-event"。在 Conditional Navigation page 上可以找到一个有用的示例,其中多次登录失败会触发多个小吃店。