gpt4 book ai didi

android - 使用两种方式绑定(bind)的可观察字段用法(删除属性更改监听器)

转载 作者:行者123 更新时间:2023-12-03 16:35:17 26 4
gpt4 key购买 nike

我在 ViewModel 中使用 Observable 字段。当 Observable 字段更新时,我更改了 UI 可见性。

这可以通过以下方式完成

object : Observable.OnPropertyChangedCallback() {
override fun onPropertyChanged(sender: Observable?, propertyId: Int) {

}

}

删除 ondestroy 中的回调。



直接在 XML 中映射,如 @{}使用双向绑定(bind)。

现在的问题是,如果使用双向绑定(bind),我该如何移除监听器?我知道 Livedata 可以替代它。

最佳答案

我不确定您在说哪个内存泄漏。

Java中的内存泄漏发生在一个对象存在很长时间并且它包含对不应再使用的其他对象的强引用,因此应该被GC销毁,但由于该强引用而仍然存在。

在 Android 中,当一些持久的对象存储对 Activity(或在某些情况下为 Fragment)的强引用时,通常会发生内存泄漏。 android 中的所有其他内存泄漏都不是那么有影响力(除了那些带有位图的内存泄漏 - 但这是一个完全不同的话题)

所以让我们回到 ObservableField 的数据绑定(bind)。及其在 ViewModel 中的回调或通过 @={} 进行双向数据绑定(bind).在大多数情况下在这两种情况下都不会发生内存泄漏 .要了解原因 - 您需要了解 Android 框架如何与 UI 一起运行,并且现在还需要了解 View 数据绑定(bind)是否有效。那么当您通过 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}"

在生成的文件中,它做了这样的事情
    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;
}


如您所见,没有 context都不是 activityfragment泄漏,因为没有对它们存储在任何地方的强引用。没有对 context 的引用, activityfragment在您的 ViewModel要么(我希望!)。此外,它的工作方式相反 - ui 商店链接到 ViewModel在绑定(bind)实现中因此我们的 ViewModel可能会泄漏。这是后置情况,因为 Activity 或 Fragment 的 UI 通常会连同它的 ActivityBindingImpl 一起被破坏。或 FragmentBindingImpl绑定(bind)但是...

确保您有手动清除引用的方法:在任一 Activity 中' onDestroy或 fragment ' 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

为了处理绑定(bind)自动清除,您可以使用 AutoClearedValue

实际用法可能看起来像(如果你不关心它的类型)
override var binding: ViewDataBinding? by autoCleared()// that is all - no need of onDestroy or onDestroyView

编辑

如果您想手动取消注册 ObservableField 中的所有回调你可以做到。最好的方法是 onCleared() ViewModel的方法.您应该调用 observableField.removeOnPropertyChangedCallback(callback)处理这些东西。考虑到 ObservableField,它看起来像这样和上面的回调声明:
class MyViewModel: ViewModel{
//ObservableField and callback declarations
...
override void onCleared(){
someField.removeOnPropertyChangedCallback(someCallback)
}

}

编辑结束

我刚刚描述的这一切确保在使用 ObservableFields 时不会出现内存泄漏。并查看数据绑定(bind)。这一切都与正确的实现有关。当然,您可以通过泄漏来实现它,但您可以在没有泄漏的情况下实现它。

如果仍有不清楚的地方发表评论 - 我会尝试扩展答案。

有关 Fragment 相关泄漏的更多信息 here

希望能帮助到你。

关于android - 使用两种方式绑定(bind)的可观察字段用法(删除属性更改监听器),我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/61801909/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com