Dagger Hilt报错User cannot be provided without an @Provides-annotated method如何解决
错误原因
- Hilt组件存在严格的层级可见性限制:
ActivityComponent的依赖仅对Activity、Fragment等同生命周期级别的组件可见,ViewModelComponent的父组件仅为SingletonComponent和ActivityRetainedComponent,完全无法访问ActivityComponent中提供的@CurrentUser User实例。 - 你将
RepositoryModule修改为@InstallIn(ActivityComponent::class)后依旧报错,是因为默认ViewModel依赖由ViewModelComponent提供,ActivityComponent的依赖无法反向传递到上层的ViewModelComponent,导致ViewModel找不到对应的ActivityRepository实例。
额外检查:请确认你的
@CurrentUser注解本身已添加@Qualifier注解,示例定义如下:@Qualifier @Retention(AnnotationRetention.BINARY) annotation class CurrentUser若未添加
@Qualifier,即使依赖层级正确也会抛出找不到提供方法的错误。
解决方法
方案1:将CurrentUser提供升级到ActivityRetainedComponent(推荐)
ActivityRetainedComponent的生命周期和ViewModel完全对齐,同时是ViewModelComponent的父组件,两处都可以正常访问依赖,修改你的User提供模块即可:
@InstallIn(ActivityRetainedComponent::class) @Module object MainActivityModule { /** Provides current user that is stored in an intent after Logged In **/ @Provides @CurrentUser fun providesCurrentUser( @ActivityContext activity: Context ): User { val intent: Intent = (activity as MainActivity).intent return intent.getSerializableExtra(CURRENT_USER) as User } }
你的RepositoryModule保持@InstallIn(ViewModelComponent::class)不变即可正常编译。
方案2:将依赖层级统一为Activity级别
如果你的业务逻辑只需要在Activity生命周期内使用Repository,可以将Repository标记为@ActivityScoped,并在Activity中注入Repository后手动传递给ViewModel,不过该方式代码侵入性较高,不符合Hilt最佳实践。
方案3:全局存储登录态放到SingletonComponent
如果CurrentUser是登录后全局通用的用户信息,不需要依赖Activity的Intent传递,可以将用户信息存储到全局缓存/SP中,将@CurrentUser User的提供模块放到SingletonComponent,整个应用所有级别的组件都可以访问该依赖。
内容的提问来源于stack exchange,提问作者Erjon
相关产品推荐
相关产品推荐

