Android JetPack的共享ViewModel生命周期

eng*_*yin 9 android model-view android-fragments android-architecture-components android-jetpack

该文件 https://developer.android.com/topic/libraries/architecture/viewmodel#sharing描述了如何在不同的片段之间共享相同的ViewModel。

我的页面有些复杂 单个“活动”应用程序中其中包含容器和选项卡片段。每个此类页面都有自己的ViewModel,应与所有包含的片段共享。

这里的关键技巧是使用Activity而不是Fragment来保存我的ViewModel。

问题是我的活动可以有多个具有自己的模型的页面,并且始终保持特定页面的视图模型是浪费设备资源。

当用户离开页面时,是否有任何方法可以控制ViewModel的生命周期以销毁它?

我想使用容器片段而不是活动:

model = ViewModelProviders.of(getPageContainerFragment()).get(SharedViewModel.class);
Run Code Online (Sandbox Code Playgroud)

但是发现这个想法不是很好,因为所有子片段都应该了解父元素,而这可能不是很好。

是否有其他方法可以正确处理这种情况?

dha*_*sky 2

如果我猜对了,你的问题是“如何释放资源”而不是“如何清除视图模型”。
因此,您可以使视图模型尽可能轻,如下所示:

abstract class MyViewModel: ViewModel() {
    abstract fun freeResources()
}
Run Code Online (Sandbox Code Playgroud)

并在页面更改时调用vm.freeResources()OnPageChangeListener或您使用的任何侦听器。 在这种情况下,您应该使用活动范围获取 viewModel。 OnTabSelectedListener

或者,如果您确实希望创建视图模型onCleared(),然后创建新的视图模型,我可以建议使用scoped-vm库。它允许您请求由字符串名称标识的范围的视图模型。

ScopedViewModelProviders
     .forScope(fragment, "scope")
     .of(activity)
     .get(MyViewModel::class.java)
Run Code Online (Sandbox Code Playgroud)

一旦从该范围请求某些内容的最后一个片段被销毁,范围就会被清除(其中的视图模型也是如此)。因此,为您的页面使用不同的范围。
但是,在这种情况下,您应该仔细检查片段的生命周期:如果您的 PagerAdapter 保留它们以供重复使用,则范围将永远不会被清除,只有手动方法才能帮助您。