【问题标题】:Shared ViewModel's onCleared() is never called共享 ViewModel 的 onCleared() 永远不会被调用
【发布时间】:2019-07-15 00:56:51
【问题描述】:

我有一个 Activity 应用程序。在应用程序的一部分中,有一个片段的主从组合,它们使用a shared ViewModel 在它们之间共享一些数据。我面临的问题是 ViewModel 的 onCleared() 方法即使在两个 Fragment 都被销毁时也不会被调用。 onCleared() 仅在活动被销毁时调用。

这是它应该如何工作的吗?因为这在单个 Activity 模型中毫无用处,因为 Activity 始终是活动的。还是我错过了什么?

【问题讨论】:

    标签: android android-fragments viewmodel


    【解决方案1】:

    不看一点代码就很难给出一个可靠的答案。我的第一个猜测是您可能将ViewModel 限定为Activity,而不是Fragment 本身。

    //inside of fragment onCreate()
    
    //scoped to fragment
    viewModel = ViewModelProviders.of(this).get(SharedViewModel::class.java)
    
    //scoped to activity
    viewModel = ViewModelProviders.of(requireActivity()).get(SharedViewModel::class.java)
    

    如果是这种情况,请查看图表以了解ViewModel 的范围。那么onCleared() 从未被调用的原因是因为您的Activity 在技术上从未被销毁,因为它使您的应用程序处于前台。

    如果这不是您问题的正确解决方案,那么我认为ViewModel 上的文档可能是开始寻找正确答案的好地方。编码愉快!

    【讨论】:

    • 我确实做到了。虽然我通过parentFragment而不是requireActivity(),但结果是一样的,因为父级是所有FragmentsActivity。如果我自己传递片段,则不会共享数据,因为每个片段都会创建自己的ViewModel。我想共享的ViewModel 不能解决我最初的问题。
    • 是的,不幸的是,我认为如果您需要在共享的ViewModel 中调用onCleared(),这实际上只有在活动被销毁时才会发生。你究竟需要在onCleared() 中执行什么?您的问题可能还有其他解决方案
    • 我有一些共享数据,所有Fragments 都需要这些数据,这些数据是从我的导航中的顶级目的地之一访问的。然而,一旦用户离开这个顶级目的地到另一个目的地,那么这些数据就不再需要并且应该被清除,所以它不会耗尽内存。我教ViewModels 可以保存这个案例,但我想我会自己写一些东西,通过Activity 共享数据,并带有手动清除共享数据的选项。
    【解决方案2】:

    如果您在ViewModelProviders.of(this) 中传递该活动,那么,是的,这就是预期的行为。要将 ViewModel 仅作用于主片段和细节片段,您可能需要为它们创建一个父片段,例如,MasterDetailFragment,它同时托管MasterFragmentDetailsFragment

    【讨论】:

    • 最好使用KTX扩展和by viewModels
    【解决方案3】:

    由于原问题中a shared ViewModel的链接已经更新,但这里的答案没有更新。因此,这是基于 Andrew Steinmetz 的答案的更新答案。

    以下是从 Google 的文档创建共享 ViewModel 的方法:

    private val model: SharedViewModel by activityViewModels()
    

    因为它使用activityViewModels,所以ViewModel 将有一个活动范围。首次使用创建后会存储在其父Activity的viewModelStore中,当Activity完成时会调用ViewModel的onCleared()

    如果ViewModel创建如下,

    private val model: SharedViewModel by viewModels()
    

    ViewModel 将只有范围作为它的片段,因为它存储在片段自己的viewModelStore 中,它可以在屏幕旋转等配置更改期间生存,但是当所有使用它的片段都完成时。它也会被销毁。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2012-10-27
      • 2013-10-12
      • 2012-03-27
      • 2013-08-29
      • 2013-11-03
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多