我的应用包含一个 Activity
多个Fragments
,遵循“单一 Activity 应用程序模型”,以便我可以使用 Navigation Component
正确实现导航在 Android 中 jetpack
.
我的大部分屏幕 ( Fragments
) 都是独立的,不相互依赖,因此它们使用自己的 ViewModel
一些功能需要导航涉及多个 Fragment
.由于这些功能在它们之间共享数据,这些数据通过 Fragments
来回传递,我使用共享 ViewModel(由 Google 推荐)。
我需要使用共享的相同实例 ViewModel
在所有相关的Fragments
,因为我需要 Fragments
共享共享的状态ViewModel
.
要使用 ViewModel
的同一个实例在这些相关的Fragments
,我需要创建 ViewModel
使用父级 Activity
(不是 Fragment
)在获取 ViewModel
时来自 ViewModelProviders
:
val viewModel = ViewModelProviders.of(
parentActivity, factory.create()
).get(SharedViewModel::class.java)
但是,这会产生一个问题:
当连续导航到第一个 Fragment
时这需要共享 ViewModel
, ViewModelProviders.of()
将返回 ViewModel
的相同实例和以前一样:ViewModel
正在 Fragments
之间共享,但也在对这样实现的功能的不同导航之间。
我明白为什么会发生这种情况(Android 将 ViewModel 存储在 map
中,在使用 ViewModel
请求 ViewModelProviders.of()
时使用它),但我不知道我应该如何实现正确地“共享 ViewModel 模式”。
我看到的唯一解决方法是:
- 创建一个不同的
Activity
对于使用Fragment
的功能与共享ViewModel
- 使用嵌套
Fragments
, 并使用共同父级Fragment
对于使用Fragment
的功能与共享ViewModel
有了这两个选项,我就可以创建一个 ViewModel
将在 Fragments
之间共享干预该功能,每次导航到该功能时都会有所不同。
我在这里看到的问题是,这似乎与 Navigation Component
的基本原理背道而驰。和单例 Activity
应用程序。
以这种方式实现的每个功能都需要具有不同的导航图,因为它们将使用不同的导航主机。这会阻止我使用 Navigation Component
的一些不错的功能。 .
实现我想要的东西的正确方法是什么? 我是否遗漏了什么,或者它就是这样吗?
之前Navigation Component
我会使用不同的 Activities
和 Fragments
并使用 Dagger
与 Activity
关联的范围/Fragment
为了达成这个。但我不确定只用一个 Activity 实现它的最佳方式是什么`
最佳答案
我发现这可以从 2.1.0-alpha02
来自: https://developer.android.com/jetpack/androidx/releases/navigation#2.1.0-alpha02
You can now create ViewModels that are scoped at a navigation graph level via the by navGraphViewModels() property delegate for Kotlin users or by using the getViewModelStore() API added to NavController. b/111614463
基本上:
- 在导航图编辑器中,创建一个嵌套图,并为其分配一个 id
- 在提供
ViewModel
时,不要从 Activity 中执行。相反,使用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>
为了将 ViewModel
范围限定为 feature_nested_graph
嵌套导航间隙:
val viewModel: SharedViewModel
by fragment.navGraphViewModels(R.id.feature_nested_graph)
或者,如果正在注入(inject) ViewModel
并且您正在为此使用自定义工厂:
val viewModel: SharedViewModel
by fragment.navGraphViewModels(R.id.feature_nested_graph) { factory2.create(assessmentId) }
关于android - 如何使用共享的 ViewModel,并避免每次使用 Navigation Component 重复使用相同的实例,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/59378823/