Ric*_*ier 36 android android-viewmodel android-architecture-components android-jetpack
参考android.arch.lifecycle.ViewModel课程.
ViewModel限定在与其相关的UI组件的生命周期中,因此在Fragment基于应用程序的应用程序中,这将是片段生命周期.这是一件好事.
在某些情况下,人们想要ViewModel在多个片段之间共享实例.具体而言,我对许多屏幕与相同基础数据相关的情况感兴趣.
(当多个相关片段显示在同一个屏幕上时,文档提出了相似的方法,但这可以通过使用单个宿主片段来解决,如下面的答案所示.)
这在官方ViewModel文档中讨论:
ViewModels还可以用作活动的不同片段之间的通信层.每个Fragment都可以通过其Activity使用相同的密钥获取ViewModel.这允许以解耦方式在片段之间进行通信,使得它们永远不需要直接与其他片段对话.
换句话说,要在表示不同屏幕的片段之间共享信息,ViewModel应将其范围限定为Activity生命周期(并且根据Android文档,这也可以在其他共享实例中使用).
现在,在新的Jetpack导航模式中,建议使用"One Activity/Many Fragments"架构.这意味着活动在应用程序使用的整个过程中都存在.
即任何ViewModel作用于Activity生命周期的共享实例永远不会被清除 - 内存仍然在不断使用.
为了保留内存并在任何时间点使用尽可能少的内容,能够ViewModel在不再需要时清除共享实例会很好.
如何ViewModel从它ViewModelStore或持有者片段手动清除?
Sak*_*boy 25
无需使用Navigation Component库的快速解决方案:
getActivity().getViewModelStore().clear();
Run Code Online (Sandbox Code Playgroud)
这将在不合并Navigation Component库的情况下解决这个问题。这也是简单的一行代码。这将清除掉那些ViewModels被共享Fragments通过Activity
Nag*_*obi 10
如果您检查代码,在这里你会发现,你可以得到ViewModelStore从ViewModelStoreOwner和Fragment,FragmentActivity例如工具,该接口。
从那里开始,您可以致电viewModelStore.clear(),正如文档所述:
/**
* Clears internal storage and notifies ViewModels that they are no longer used.
*/
public final void clear() {
for (ViewModel vm : mMap.values()) {
vm.clear();
}
mMap.clear();
}
Run Code Online (Sandbox Code Playgroud)
注意:这将清除特定LifeCycleOwner的所有可用ViewModel,这不允许您清除一个特定的ViewModel。
如果您不希望ViewModel将范围限定为Activity生命周期,则可以将其限定为父片段的生命周期。因此,如果您想ViewModel在屏幕中与多个片段共享 的实例,则可以对这些片段进行布局,使它们都共享一个公共父片段。这样,当您实例化时,ViewModel您可以这样做:
CommonViewModel viewModel = ViewModelProviders.of(getParentFragment()).class(CommonViewModel.class);
Run Code Online (Sandbox Code Playgroud)
希望这会有所帮助!
我想我有更好的解决方案。
正如@Nagy Robi 所说,您可以清除ViewModelby call viewModelStore.clear()。这样做的问题是它会清除此范围内的所有视图模型ViewModelStore。换句话说,您将无法控制ViewModel要清除的内容。
但根据@mikehc这里。我们实际上可以创建我们自己的ViewModelStore。这将允许我们精细控制 ViewModel 必须存在的范围。
注意:我还没有看到有人这样做过,但我希望这是一个有效的方法。这将是在单个活动应用程序中控制范围的好方法。
请对这种方法提供一些反馈。任何事情都会受到赞赏。
从Navigation Component v2.1.0-alpha02 开始,ViewModels 现在可以限定为流。这样做的缺点是您必须实施Navigation Component到您的项目中,并且您无法对ViewModel. 但这似乎是一件更好的事情。
正如 OP 和 Archie 所说,谷歌让我们能够将 ViewModel 范围限定为导航图。如果您已经在使用导航组件,我将在此处添加如何操作。
您可以在导航图中选择需要组合在一起的所有片段,然后 right-click->move to nested graph->new graph
现在这会将选定的片段移动到主导航图中的嵌套图,如下所示:
<navigation app:startDestination="@id/homeFragment" ...>
<fragment android:id="@+id/homeFragment" .../>
<fragment android:id="@+id/productListFragment" .../>
<fragment android:id="@+id/productFragment" .../>
<fragment android:id="@+id/bargainFragment" .../>
<navigation
android:id="@+id/checkout_graph"
app:startDestination="@id/cartFragment">
<fragment android:id="@+id/orderSummaryFragment".../>
<fragment android:id="@+id/addressFragment" .../>
<fragment android:id="@+id/paymentFragment" .../>
<fragment android:id="@+id/cartFragment" .../>
</navigation>
</navigation>
Run Code Online (Sandbox Code Playgroud)
现在,当您初始化视图模型时,在片段内部执行此操作
val viewModel: CheckoutViewModel by navGraphViewModels(R.id.checkout_graph)
Run Code Online (Sandbox Code Playgroud)
如果您需要传递视图模型工厂(可能用于注入视图模型),您可以这样做:
val viewModel: CheckoutViewModel by navGraphViewModels(R.id.checkout_graph) { viewModelFactory }
Run Code Online (Sandbox Code Playgroud)
确保它R.id.checkout_graph而不是R.navigation.checkout_graph
出于某种原因,创建导航图并将include其嵌套在主导航图中对我不起作用。大概是个bug。
来源:https : //medium.com/androiddevelopers/viewmodels-with-saved-state-jetpack-navigation-data-binding-and-coroutines-df476b78144e
谢谢,OP 和@Archie 为我指明了正确的方向。
| 归档时间: |
|
| 查看次数: |
7780 次 |
| 最近记录: |