因此,我使用导航实现了具有多个 fragment 模式的单个 Activity 。我为每个 fragment 使用了非用户界面操作的 View 模型。
问题是当您使用 findNavController().navigate()
导航时, fragment 实际上并没有被销毁。只有 onDestroyView
叫做。因此, fragment 的 onDestroy 永远不会被调用,随后 View 模型也不会被清除,因此 LiveData 观察者也保持 Activity 状态,当我回到 fragment 时,再次创建观察者,因此观察到两次实时数据。一次是它拥有的旧数据,第二次是来自某些操作的新数据。
例如,
我有 fragment 一个 和 fragment 乙
一个 显示列表和 乙您可以添加将在列表中显示的内容。可能从 fragment 中的 api 获取新数据乙显示在一个 .
所以,当我从 fragment 返回时乙至一个 观察者被调用两次,首先是旧数据,然后是更新数据。最后,列表显示了正确的数据,但我不希望有两个观察者发生。
我关注了这篇文章
https://medium.com/@BladeCoder/architecture-components-pitfalls-part-1-9300dd969808
并尝试使用 viewLifeCycleOwner
而不是 this
但这无济于事,问题仍然存在。
我还尝试在观察之前删除观察者:
vm.ld.removeObservers(this)
vm.ld.observe(viewLifeCyclerOwner, observer)
问题仍然存在。
(我也尝试删除
onDestroyView
中的观察者,但问题仍然存在。)我发现的唯一解决方法是手动调用 View 模型
onCleared
在 onDestroyView
并清除实时数据。在 fragment onDestroyView
vm.clear()
在 View 模型
fun clear() = onCleared()
override fun onCleared() {
//do stuff
}
现在,这解决了我的问题。但我觉得这不是一个可靠的解决方案,可以有更好的方法来做到这一点。如果有人能阐明这一点,我会很高兴。谢谢。
最佳答案
我浪费了几天时间来解决类似的问题。仔细检查您的 VM 是如何初始化的:
val myVm: MyViewModel by activityViewModels()
对比val myVm: MyViewModel by viewModels()
如果您使用 by activityViewModels()
委托(delegate),您正在指示 Android 将 VM 的生命周期与主机 Activity 而不是当前 fragment 绑定(bind)。因此,即使 fragment 被销毁,您的 VM 也不会被清除。我经过惨痛的教训才学到这个。切换回 by viewModels()
delegate 将 VM 的范围限制在 Fragment 的生命周期内。当 Fragment 被销毁时,如果它是唯一的观察者,VM 将清除。我完全被
this
弄糊涂了与 viewLifecycleOwner
观察时的目标。显然,目标的选择只与您是否打算手动控制显示 DialogFragment 的对话框有关。另一个困惑的 gem 。在您的情况下,如果您在 fragment 和
onDestroy
之间切换没有被调用,也可能是因为 fragment 被保留了。例如,ViewPager2
有 offscreenPageLimit
,它指示 Android 在您切换页面时将隐藏的 fragment 保留在内存中,这进一步增加了必须完全了解所有内容才能使用 SDK 的困惑局面。
关于android - ViewModel 在导航导航中没有被清除,并且 viewmodel 中的实时数据保持 Activity 状态,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/59373364/