android - ViewModel 在导航导航中没有被清除,并且 viewmodel 中的实时数据保持 Activity 状态

标签 android android-fragments navigation android-livedata android-viewmodel

因此,我使用导航实现了具有多个 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 模型 onClearedonDestroyView并清除实时数据。

在 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 被保留了。例如,ViewPager2offscreenPageLimit ,它指示 Android 在您切换页面时将隐藏的 fragment 保留在内存中,这进一步增加了必须完全了解所有内容才能使用 SDK 的困惑局面。

关于android - ViewModel 在导航导航中没有被清除,并且 viewmodel 中的实时数据保持 Activity 状态,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/59373364/

相关文章:

html - CSS 移动导航菜单 - 下拉菜单嵌套不正确

java - 应用程序崩溃,没有错误

javascript - Android jQuery fadeIn 奇怪的行为

java - 使用我的应用程序连接到 php .htaccess

安卓, Kotlin : how can I only allow my view pager swiping on the left when needed

html - 如何微调这个导航栏?

android - 使用 Mosby 实现非 ViewGroup MVP Android View

android - 部 fragment 段项目隐藏在操作栏下

android - 使用 fragment 更改为横向时 map 行为会发生变化

css - 为什么 Percent-Padded CSS 列表项在点击时改变宽度?