Android Dagger Hilt:我们是否需要 ViewModel 的范围注释?

Mac*_*ter 3 android dagger android-viewmodel dagger-hilt

在我的应用程序中,我有一个需要访问 ViewModel 的 MainActivity。我正在使用 DaggerHilt 和 @ViewModelInject 注释注入 ViewModel。此外,我在 Activity 中有两个 Fragment,它们需要访问同一个 ViewModel,以便使用 observable 相互传递数据。

问题:我发现每当我的一个 Fragment 通过onDestroy()它的 ViewModel 时就会被杀死。这让我认为 Activity 和 Fragment 没有共享同一个 ViewModel。

我的问题:有谁知道我们是否应该在 Dagger Hilt 中为 ViewModel 使用范围注释?我在 Hilt 文档或 android 开发教程/指南中没有看到这一点。我曾假设他们正在制作 ViewModels 应用程序级别的单例,这是有道理的。

如果我们必须为 ViewModel 使用范围注释,有没有人知道哪个级别合适?

这是我的视图模型代码:

class MainActivityViewModel @ViewModelInject constructor(
    private val repo: Repo,
    private val rxSharedPrefsRepo: RxSharedPrefsRepo,
    private val resourcesRepo: ResourcesRepo,
    @Assisted private val savedStateHandle: SavedStateHandle
) : ViewModel() {
Run Code Online (Sandbox Code Playgroud)

ian*_*ake 13

根据Android 中作用域和 Hilt 博客文章,使用@ViewModelInject意味着您传递到 ViewModel 的对象的作用域是 ViewModel。

但是,ViewModel 的范围基于您获取 ViewModel 的方式(ViewModelStore与 ViewModel 关联的内容)——而不是 Hilt 控制的任何内容。如果您by viewModels()在 Fragment 中使用,则 ViewModel 的范围仅限于 Fragment。如果您使用by activityViewModels()by navGraphViewModels(),则 ViewModel 将分别限定为活动或导航图。

正如博客文章中提到的,如果您想要一个对象范围限定于活动并且在配置更改后仍然存在,您可以@ActivityRetainedScoped在任何对象上使用 Hilt并将该对象注入到两个片段中。

@ActivityRetainedScoped博客文章中介绍了您应该使用还是使用 ViewModel 来独立于 Hilt 控制范围:

使用 Hilt 进行范围界定的优点是范围类型在 Hilt 组件层次结构中可用,而使用 ViewModel,您必须从 ViewModel 手动访问范围类型。

使用 ViewModel 进行范围界定的优势在于,您可以为应用程序中的任何 LifecycleOwner 对象使用 ViewModel。例如,如果您使用 Jetpack Navigation 库,则可以将 ViewModel 附加到您的 NavGraph。

Hilt 提供有限数量的范围。您可能会发现您没有特定用例的范围——例如,在使用嵌套片段时。对于这种情况,您可以回退到使用 ViewModel 进行范围界定。

  • 请注意,您还可以使用“by viewmodels ({requireParentFragment()})”将 ViewModel 范围限定为父片段。如果您的父片段并不在活动期间一直存在,那么这一点就很重要。 (2认同)