我不确定您说的是哪种内存泄漏。
Java中的内存泄漏发生在一个对象存在很长时间并且它包含对不应再使用的其他对象的强引用,因此应该被GC销毁,但由于该强引用而仍然存在。
在 Android 中,内存泄漏通常发生在某些持久对象存储对 Activity(或在某些情况下为 Fragment)的强引用时。 android 中的所有其他内存泄漏都没有那么大的影响(位图除外 - 但这是一个完全不同的话题)
所以让我们返回到使用ObservableField 的数据绑定及其在ViewModel 内的回调或通过@={} 的双向数据绑定。在大多数情况下在这两种情况下都不会发生内存泄漏。要了解原因 - 您需要了解 Android 框架如何与 UI 一起运行,并且现在还需要了解视图数据绑定是否有效。那么当您通过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 也没有activity 或fragment 泄漏,因为在任何地方都没有对它们的强引用。在您的ViewModel 中也没有提到context、activity 或fragment(我希望!)。此外,它以相反的方式工作 - ui 在绑定实现中存储指向ViewModel 的链接,因此我们的ViewModel 可能会泄漏。这是后置情况,因为 Activity 或 Fragment 的 UI 通常会连同其 ActivityBindingImpl 或 FragmentBindingImpl 绑定一起被破坏,但是......
确保您有手动清除引用的方法:在 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
还可以使用AutoClearedValue处理绑定自动清除
实际用法可能看起来像(如果你不关心它的类型)
override var binding: ViewDataBinding? by autoCleared()// that is all - no need of onDestroy or onDestroyView
编辑
如果您想手动取消注册 ObservableFields 中的所有回调,您可以这样做。最好的方法是使用ViewModel 的onCleared() 方法。你应该打电话给observableField.removeOnPropertyChangedCallback(callback) 来处理这些东西。考虑到ObservableField 和上面的回调声明,它看起来像这样:
class MyViewModel: ViewModel{
//ObservableField and callback declarations
...
override void onCleared(){
someField.removeOnPropertyChangedCallback(someCallback)
}
}
编辑结束
我刚才描述的这一切确保在使用ObservableFields 和查看数据绑定时不会出现内存泄漏。这一切都与正确的实施有关。当然你可以用泄漏来实现它,但你可以不用泄漏来实现它。
如果仍有不清楚的地方发表评论 - 我会尝试扩展答案。
更多关于 Fragment 依赖泄漏的信息here
希望对你有帮助。