Android Dagger Hilt:我们需要 ViewModel 的范围注解吗?

Android Dagger Hilt: Do we need scope annotations for ViewModels?

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

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

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

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

这是我的视图模型代码:

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

根据 Scoping in Android and Hilt blog post,使用 @ViewModelInject 意味着您传递到 ViewModel 的对象在 ViewModel 范围内。

但是,ViewModel 的范围取决于您获取 ViewModel 的方式(ViewModelStore ViewModel 与什么相关联)——而不是 Hilt 控制的任何内容。如果您使用 by viewModels() in a Fragment, then the ViewModel is scoped to the Fragment. If you use by activityViewModels() or by navGraphViewModels(),则 ViewModel 的范围将分别限定为 activity 或导航图。

如博客 post 中所述,如果您想要一个作用域为 activity 并且在配置更改后仍然存在的对象,您可以在任何对象上使用 Hilt 的 @ActivityRetainedScoped 并注入该对象分为两个片段。

博客 post:

中介绍了您应该使用 @ActivityRetainedScoped 还是单独控制 Hilt 范围的 ViewModel

The advantage of scoping with Hilt is that scoped types are available in the Hilt component hierarchy whereas with ViewModel, you have to manually access the scoped types from the ViewModel.

The advantage of scoping with ViewModel is that you can have ViewModels for any LifecycleOwner objects in your application. For example, if you use the Jetpack Navigation library, you can have a ViewModel attached to your NavGraph.

Hilt provides a limited number of scopes. You might find that you don’t have a scope for your particular use case — for example, when using nested fragments. For that case, you can fall back to scoping using ViewModel.