2

我的应用由一个Activity和多个组成Fragments,遵循“单个 Activity 应用模型”,因此我可以使用Navigation ComponentAndroid 中的 正确导航jetpack

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

有些功能需要涉及多个导航Fragment。由于这些功能在它们之间共享通过 来回传递的数据Fragments,因此我使用共享的 ViewModel(如 Google 推荐的那样)。我需要ViewModel在所有关联中使用相同的共享实例Fragments,因为我需要Fragments共享共享的状态ViewModel

ViewModel要在这些关联中使用相同的实例Fragments,我需要在从以下获取时创建ViewModel使用父级Activity(而不是Fragment):ViewModelViewModelProviders

val viewModel = ViewModelProviders.of(
            parentActivity, factory.create()
        ).get(SharedViewModel::class.java)

但是,这可行,它会产生一个问题:当连续导航到Fragment需要 shared的第一个时ViewModelViewModelProviders.of()将返回与ViewModel以前相同的实例:在ViewModel之间共享Fragments,但也在不同导航之间实现了类似的功能这个。

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

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

  • 为使用共享Activity功能的功能创建一个不同的FragmentViewModel
  • 使用嵌套,并为使用共享的功能Fragments使用公共父级FragmentFragmentViewModel

使用这两个选项,我将能够创建一个ViewModelFragments在功能干预之间共享,并且每次导航到该功能时都会有所不同。

我在这里看到的问题是,这似乎Navigation Component与单个Activity应用程序的基本原理背道而驰。以这种方式实现的每个功能都需要具有不同的导航图,因为它们将使用不同的导航主机。这会阻止我使用Navigation Component.

实现我想要的正确方法是什么?我错过了什么,还是它就是这样?

之前Navigation Component我会使用不同的ActivitiesandFragments和使用与/Dagger关联的范围来实现这一点。但我不确定只用一个 Activity 来实现它的最佳方法是什么ActivityFragment

4

2 回答 2

2

我发现这可以从开始2.1.0-alpha02

来自: https ://developer.android.com/jetpack/androidx/releases/navigation#2.1.0-alpha02

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

基本上:

  1. 在导航图编辑器中,创建一个嵌套图,为其分配一个 id
  2. 提供时ViewModel,不要从 Activity 中进行。而是navGraphViewModels使用Fragment.

例子:

导航图中的嵌套图

<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>

为了获得嵌套导航间隙的ViewModel范围:feature_nested_graph

        val viewModel: SharedViewModel
                by fragment.navGraphViewModels(R.id.feature_nested_graph)

或者,如果正在注入ViewModel并且您正在为此使用自定义工厂:

        val viewModel: SharedViewModel
                by fragment.navGraphViewModels(R.id.feature_nested_graph) { factory2.create(assessmentId) }
于 2019-12-18T12:41:29.557 回答
0

你有一个 shared 的相同实例ViewModel,因为它属于Activity- 这很清楚。我不确切知道您的用例,但通常当我需要做类似的事情时,我只是通知ViewModelfromFragment's onCreateorCreateView传递一些标识符。在你的情况下,它可能是这样的:

viewModel.onNavigatedTo("fragment1")

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

于 2019-12-17T19:04:07.710 回答