You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Android Dagger Hilt:共享ViewModel是否需添加作用域注解?

解决Activity与Fragment共享ViewModel的问题(Dagger Hilt场景)

嘿,我来帮你理清这个问题!首先得纠正一个关键误解:ViewModel默认不是应用级单例,它的生命周期是绑定到你获取它时指定的ViewModelStoreOwner(比如Activity或Fragment)的。你遇到的Fragment销毁时ViewModel跟着销毁的情况,本质是每个Fragment都创建了自己的ViewModel实例,而不是共享Activity的那一个。

关于Dagger Hilt中ViewModel的作用域

首先明确:ViewModel本身不需要添加Hilt的作用域注解(比如@Singleton、@ActivityScoped这些)。Hilt的@ViewModelInject只是负责帮你注入ViewModel构造函数里的依赖(比如你的Repo、RxSharedPrefsRepo),而ViewModel的实例生命周期是由ViewModelStoreOwner决定的,和Hilt的依赖作用域是两个独立的概念。

如何让Activity和Fragment共享同一个ViewModel

问题的核心不在ViewModel的注入写法,而在获取ViewModel的方式:

  • 在你的MainActivity中,正常获取ViewModel:
    private val viewModel: MainActivityViewModel by viewModels()
    
  • 在两个Fragment中,必须传入Activity作为ViewModelStoreOwner,而不是用Fragment自身的:
    private val viewModel: MainActivityViewModel by viewModels({ requireActivity() })
    
    如果你不用KTX扩展,用原始的ViewModelProvider写法也是一样的:
    val viewModel = ViewModelProvider(requireActivity()).get(MainActivityViewModel::class.java)
    

这样一来,三个组件(Activity+两个Fragment)就会共享同一个ViewModel实例,只有当Activity销毁时,这个ViewModel才会被清理,Fragment的销毁不会影响它的生命周期。

再说说你的ViewModel代码

你当前的ViewModel写法是完全正确的:

class MainActivityViewModel @ViewModelInject constructor(
    private val repo: Repo,
    private val rxSharedPrefsRepo: RxSharedPrefsRepo,
    private val resourcesRepo: ResourcesRepo,
    @Assisted private val savedStateHandle: SavedStateHandle
) : ViewModel() {
    // ...你的业务逻辑
}

@ViewModelInject和@Assisted SavedStateHandle的使用都符合Hilt的规范,不需要修改这部分代码。

额外补充:Hilt作用域注解的用途

如果你的依赖(比如Repo)需要和Activity同生命周期,可以给它加@ActivityScoped注解,但这只是控制依赖本身的实例范围,和ViewModel的生命周期没有直接关联。ViewModel的生命周期始终由绑定的ViewModelStoreOwner决定。

内容的提问来源于stack exchange,提问作者Mackalester

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.08 19:57:57