数据绑定是否会从实现 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 属性。
另一件事...虽然我没有验证行为,但源代码似乎表明弱引用用于 ObservableField
、ObservableList
、ObservableMap
等。
LiveData
之所以不同,有以下几个原因:
- The documentation for
LiveData.observe
表示在生命周期所有者被销毁之前,对观察者和生命周期所有者都有一个强引用。
LiveData
发出的信号与 ObservableField
不同。 LiveData
将在调用 setValue
或 postValue
时发出,而不考虑值是否实际更改。 ObservableField
并非如此。出于这个原因,LiveData
可以通过多次设置相同的值来发送有点 "pseudo-event"。在 Conditional Navigation page 上可以找到一个有用的示例,其中多次登录失败会触发多个小吃店。
对于我的 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 属性。
另一件事...虽然我没有验证行为,但源代码似乎表明弱引用用于 ObservableField
、ObservableList
、ObservableMap
等。
LiveData
之所以不同,有以下几个原因:
- The documentation for
LiveData.observe
表示在生命周期所有者被销毁之前,对观察者和生命周期所有者都有一个强引用。 LiveData
发出的信号与ObservableField
不同。LiveData
将在调用setValue
或postValue
时发出,而不考虑值是否实际更改。ObservableField
并非如此。出于这个原因,LiveData
可以通过多次设置相同的值来发送有点 "pseudo-event"。在 Conditional Navigation page 上可以找到一个有用的示例,其中多次登录失败会触发多个小吃店。