Hilt多作用域绑定问题:ActivityScoped依赖注入ViewModel报错如何解决?
报错根本原因
Hilt 组件存在严格的层级访问规则:低层级组件可以访问高层级组件的绑定,高层级组件无法访问低层级的绑定。你当前的依赖链路存在层级冲突:ActivityComponent(你存放LocationService绑定的组件)层级低于 ViewModelComponent(MapScreenViewModel 所属的组件),ViewModel 所在的组件完全看不到 ActivityComponent 中声明的绑定,因此抛出 MissingBinding 错误。
解决方案
根据你的业务场景可选以下三种方案,优先推荐方案1:
方案1:改用 Application 上下文(绝大多数场景适用)
如果你的定位逻辑不需要依赖 Activity 特有能力(比如无需关联Activity生命周期、无需申请Activity级别的权限),直接将注入的上下文替换为全局Application上下文,即可将定位服务改回单例,完全避开作用域冲突:
@Singleton class LocationProviderImpl @Inject constructor( @ApplicationContext private val context: Context ) : LocationService {}
将对应的provideLocationService方法放回原来的MyAppModule中即可,ViewModel可正常注入使用。
方案2:必须使用Activity上下文的场景
如果确实需要持有Activity实例(比如要在定位服务中直接申请运行时权限),则不能将@ActivityScoped的定位服务直接注入到ViewModel中,需要调整注入位置:
- 将LocationService注入到对应业务的Activity/Fragment中
- 在Activity/Fragment获取到定位服务实例后,通过方法调用、接口回调的方式传给ViewModel使用即可
方案3:需保留ViewModel构造注入的特殊场景
如果一定要通过ViewModel构造注入定位服务,同时需要绑定Activity上下文,可以使用Hilt的辅助注入(Assisted Inject)能力,在ViewModel初始化时手动传入Activity实例构造定位服务,该方案代码复杂度较高,非必要不推荐使用。
内容的提问来源于stack exchange,提问作者Vahid
相关产品推荐
相关产品推荐

