Warning: file_get_contents(/data/phpspider/zhask/data//catemap/8/.htaccess/5.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Android 如何使用共享ViewModel,并避免每次使用导航组件时重复使用同一个ViewModel实例_Android_Dagger_Android Viewmodel_Android Jetpack Navigation_Android Navigation Graph - Fatal编程技术网

Android 如何使用共享ViewModel,并避免每次使用导航组件时重复使用同一个ViewModel实例

Android 如何使用共享ViewModel,并避免每次使用导航组件时重复使用同一个ViewModel实例,android,dagger,android-viewmodel,android-jetpack-navigation,android-navigation-graph,Android,Dagger,Android Viewmodel,Android Jetpack Navigation,Android Navigation Graph,我的应用程序由一个活动和多个片段组成,遵循“单一活动应用程序模型”,因此我可以使用Androidjetpack中的导航组件正确实现导航 我的大多数屏幕(Fragments)是独立的,彼此不依赖,因此它们使用自己的ViewModel 有些功能需要涉及多个片段的导航。由于这些功能在它们之间共享通过片段来回传递的数据,我使用共享视图模型(如谷歌推荐的)。 我需要在所有关联的片段中使用共享视图模型的相同实例,就像我需要片段共享视图模型的状态一样 要在这些关联的片段中使用视图模型的相同实例,我需要在从视图

我的应用程序由一个
活动
和多个
片段组成,遵循“单一活动应用程序模型”,因此我可以使用Android
jetpack
中的
导航组件
正确实现导航

我的大多数屏幕(
Fragments
)是独立的,彼此不依赖,因此它们使用自己的
ViewModel

有些功能需要涉及多个
片段的导航。由于这些功能在它们之间共享通过
片段来回传递的数据,我使用共享视图模型(如谷歌推荐的)。
我需要在所有关联的
片段
中使用共享
视图模型
的相同实例,就像我需要
片段
共享
视图模型
的状态一样

要在这些关联的
片段
中使用
视图模型
的相同实例,我需要在从
视图模型提供程序
获取
视图模型
时,使用父
活动
(而不是
片段
)创建
视图模型

val viewModel = ViewModelProviders.of(
            parentActivity, factory.create()
        ).get(SharedViewModel::class.java)
然而,这是可行的,它产生了一个问题: 当连续多次导航到需要共享的
ViewModel
的第一个
片段时,
ViewModelProviders.of()
将返回与前面相同的
ViewModel
实例:在
片段之间共享
ViewModel
,但也可以在不同的导航之间切换到这样实现的功能

我理解为什么会发生这种情况(Android将ViewModel存储在
映射中,当使用
ViewModelProviders.of()
请求
ViewModel
时使用该映射),但我不知道如何正确实现“共享ViewModel模式”

我看到的唯一解决办法是:

  • 为使用共享
    视图模型的
    片段的功能创建不同的
    活动
  • 使用嵌套的
    片段
    ,对于将
    片段
    与共享的
    视图模型一起使用的功能,使用公共父级
    片段
有了这两个选项,我将能够创建一个
ViewModel
,它将在介入该功能的
片段之间共享,并且每次导航到该功能时都会有所不同

我在这里看到的问题是,这似乎违背了
导航组件
和单个
活动
应用程序的基本原理。 以这种方式实现的每个功能都需要有不同的导航图,因为它们将使用不同的导航主机。这将阻止我使用
导航组件的一些优秀功能

实现我想要的东西的正确方法是什么? 我是否遗漏了什么,或者是这样的吗


导航组件之前
我将使用不同的
活动
片段
,并使用与
活动
/
片段
关联的
匕首
范围来实现这一点。但是我不确定用一个活动来实现这一点的最佳方式是什么`

您有一个共享的
视图模型的相同实例,因为它属于
活动
——这很清楚。我不清楚您的用例,但通常当我需要执行类似操作时,我只需从
Fragment的
onCreate
或createview
传递一些标识符来通知
ViewModel
。在您的情况下,它可能类似于:

viewModel.onNavigatedTo("fragment1")

通过这种方式,共享视图模型可以区分当前使用它的片段并相应地刷新状态。

我发现可以从
2.1.0-alpha02

发件人:

现在,您可以创建范围在导航图上的视图模型 通过Kotlin的by navGraphViewModels()属性委托的级别 用户或使用添加到NavController的getViewModelStore()API。 b/111614463

基本上:

  • 在导航图形编辑器中,创建嵌套图形,并为其指定一个id
  • 提供
    视图模型时,不要从活动中执行此操作。相反,使用
    
    Fragment
    navGraphViewModels
    扩展函数
  • 例如:

    导航图中的嵌套图

    <navigation
            android:id="@+id/feature_nested_graph"
            android:label="Feature"
            app:startDestination="@id/firstFragment">
            <argument
                android:name="item_id"
                app:argType="integer" />
            <fragment
                android:id="@+id/firstFragment"
                [....]
            </fragment>
            [....]
        </navigation>
    
    或者,如果您正在注入
    视图模型
    ,并且正在为此使用自定义工厂:

            val viewModel: SharedViewModel
                    by fragment.navGraphViewModels(R.id.feature_nested_graph) { factory2.create(assessmentId) }
    
            val viewModel: SharedViewModel
                    by fragment.navGraphViewModels(R.id.feature_nested_graph) { factory2.create(assessmentId) }