我正在使用导航组件,我希望在几个片段之间共享一个视图模型,但是当我离开片段时,应该将它们清除(因此不能将它们限定在活动范围内)活动很多碎片的方法。我已经设法使用多个导航主机并使用getParentFragment对片段进行作用域限定,但这只会导致更多问题,必须将片段包装在其他父片段中,使后退按钮无缝工作,其他黑客无法正常工作非常简单。有谁对如何实现这一目标有个好主意?我想知道getViewModelStore是否可以使用,鉴于下面的图像,我想将视图模型的作用域限定为createCardFragment2,并在其后的任何内容中使用它(addPredictions,editImageFragment和我尚未添加的其他东西),但是如果我导航回到mainFragment,我想清除视图模型。
顺便说一句,我不能只在mainFragment视图模型存储上调用clear,因为这里还有其他不应清除的视图模型,我想我想要一种方法来告诉nav主机我知道的父片段应该是什么如果我要从mainFragment或cardPreviewFragment导航,那将不是一件事情,也不是一种使视图模型新的方法
答案 0 :(得分:2)
以下是Alex H接受的答案的具体示例。
在您的build.gradle(应用程序)中
dependencies {
def nav_version = "2.1.0"
implementation "androidx.navigation:navigation-fragment-ktx:$nav_version"
}
视图模型示例
class MyViewModel : ViewModel() {
val name: MutableLiveData<String> = MutableLiveData()
}
在您的FirstFlowFragment.kt中定义
val myViewModel: MyViewModel by navGraphViewModels(R.id.your_nested_nav_id)
myViewModel.name.value = "Cool Name"
然后在您的SecondFlowFragment.kt中定义
val myViewModel: MyViewModel by navGraphViewModels(R.id.your_nested_nav_id)
val name = myViewModel.name.value.orEmpty()
Log.d("tag", "welcome $name!")
现在,ViewModel的作用域位于此嵌套片段中,当嵌套导航被销毁时,共享状态也将被销毁,无需手动重置它们。
答案 1 :(得分:2)
因此,当我发布此功能时,该功能已存在,但并未按预期工作,因为从那时起,我一直在使用此功能,并且这个问题越来越引起人们的关注,因此我想发布一个最新的示例,>
使用
//Navigation
implementation "androidx.navigation:navigation-fragment:2.2.0-rc04"
// Navigation UI
implementation "androidx.navigation:navigation-ui:2.2.0-rc04"
我这样得到视图模型商店的所有者
private ViewModelStoreOwner getStoreOwner() {
NavController navController = Navigation
.findNavController(requireActivity(), R.id.root_navigator_fragment);
return navController.getViewModelStoreOwner(R.id.root_navigator);
}
我使用了一个活动多个片段的实现,但是使用这个我可以有效地将我的视图模型绑定到范围限定的片段,并且使用新的live data,您甚至可以限制它
第一个ID来自导航图片段
<?xml version="1.0" encoding="utf-8"?>
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
xmlns:app="http://schemas.android.com/apk/res-auto">
<fragment
android:id="@+id/root_navigator_fragment"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:name="androidx.navigation.fragment.NavHostFragment"
app:defaultNavHost="true"
app:navGraph="@navigation/root_navigator"/>
</FrameLayout>
第二个来自导航图的ID
<?xml version="1.0" encoding="utf-8"?>
<navigation xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:id="@+id/root_navigator"
app:startDestination="@id/mainNavFragment">
然后您可以像这样使用它
private void setUpSearchViewModel() {
searchViewModel = new ViewModelProvider(getStoreOwner()).get(SearchViewModel.class);
}
答案 2 :(得分:0)
是的,现在可以将视图模型的范围从androidx.navigation:*:2.1.0-alpha02
扩展到导航图。请参阅发行说明here和API here的示例。您需要提供的只是导航图的R.id
。不过,我发现使用起来有些烦人,因为通常在onCreate
中初始化视图模型,在此范围内这是不可能的,因为还不能保证由nav主机片段设置nav控制器(我我发现配置更改就是这种情况。
此外,如果您不希望您的mainFragment
成为该范围的一部分,我建议您将其取出,并可能使用nested nav graph。