Roc*_*kin 5 android android-databinding android-architecture-components
我在 ViewModel 中使用 Observable 字段。当 Observable 字段更新时,我会更改 UI 可见性。
这可以通过
object : Observable.OnPropertyChangedCallback() {
override fun onPropertyChanged(sender: Observable?, propertyId: Int) {
}
}
Run Code Online (Sandbox Code Playgroud)
删除 ondestroy 中的回调。
或者
直接在 XML 中映射,就像@{}使用双向绑定一样。
现在的问题是,如果使用双向绑定,如何删除侦听器?我知道 Livedata 可以替代它。
我不确定你在谈论哪种内存泄漏。
Java中的内存泄漏是指一个对象存在很长一段时间,并且它包含对不应该再使用的其他对象的强引用,因此应该被GC销毁,但由于该强引用而仍然存在。
在 Android 中,当某些持久对象存储对 Activity(或在某些情况下为 Fragment)的强引用时,通常会发生内存泄漏。Android 中的所有其他内存泄漏都没有那么有影响(除了带有位图的内存泄漏 - 但这是一个完全不同的主题)
因此,让我们回到通过 的数据绑定及其在双向数据绑定ObservableField中的回调。在大多数情况下,这两种情况都不会发生内存泄漏。要了解原因 - 您需要了解 Android 框架如何使用 UI 进行操作,并且还需要了解视图数据绑定现在是否有效。那么,当您通过and 回调或 with创建回调时会发生什么ViewModel@={}ObservableField@={}
当你写的时候
val someField: ObservabaleField = ObservableFiled<String>("someText")
val someCallback = object : Observable.OnPropertyChangedCallback() {
override fun onPropertyChanged(sender: Observable?, propertyId: Int) {
}
}
someField.addOnPropertyChangedCallback(someCallback)
// and in the layout
android:text="@={viewModel.someField}"
Run Code Online (Sandbox Code Playgroud)
在生成的文件中它做了类似的事情
androidx.databinding.adapters.TextViewBindingAdapter.setText(this.mboundView1, viewModelSomeFieldGet);
@Override
protected boolean onFieldChange(int localFieldId, Object object, int fieldId) {
switch (localFieldId) {
case 0 :
//...
return onChangeViewModelSomeOtherStuff(object, fieldId);
case 1 :
return onChangeViewModelSomeField((androidx.databinding.ObservableField<java.lang.String>) object, fieldId);
}
return false;
}
Run Code Online (Sandbox Code Playgroud)
正如您所看到的,不存在任何context泄漏activity或fragment泄漏,因为没有对它们存储在任何地方的强引用。您的任何一个中都没有提到context,activity或(我希望!)。此外,它的工作方式相反 - ui 存储到绑定实现中的链接,因此我们可能会泄漏。这是后例,因为 Activity 或 Fragment 的 UI 通常会与其绑定一起被破坏,但是......fragmentViewModelViewModelViewModelActivityBindingImplFragmentBindingImpl
确保您有手动方式清除引用:在“活动”onDestroy或“片段”onDestroyView调用中
clearFindViewByIdCache()
binding.unbind()
binding = null
// if you store view link in your viewModel(which is bad and may cause leaks) this is the perfect place to nullify it
viewModel.view = null
Run Code Online (Sandbox Code Playgroud)
另外,为了处理绑定自动清除,您可以使用AutoClearedValue
实际用法可能看起来像(如果你不关心它的类型)
override var binding: ViewDataBinding? by autoCleared()// that is all - no need of onDestroy or onDestroyView
Run Code Online (Sandbox Code Playgroud)
编辑
如果您想手动取消注册 s 中的所有回调,ObservableField您可以这样做。最好的方法是使用onCleared()的方法ViewModel。你应该打电话observableField.removeOnPropertyChangedCallback(callback)来处理这些事情。ObservableField考虑到上面的回调声明,它看起来像这样:
class MyViewModel: ViewModel{
//ObservableField and callback declarations
...
override void onCleared(){
someField.removeOnPropertyChangedCallback(someCallback)
}
}
Run Code Online (Sandbox Code Playgroud)
编辑结束
我刚刚描述的所有内容可确保在使用ObservableFields和查看数据绑定时不会出现内存泄漏。这一切都与正确的实施有关。当然,你可以在有泄漏的情况下实现它,但你也可以在没有泄漏的情况下实现它。
如果仍有不清楚的地方请评论 - 我会尝试扩展答案。
有关片段相关泄漏的更多信息请参见此处
希望能帮助到你。
| 归档时间: |
|
| 查看次数: |
1333 次 |
| 最近记录: |