Android开发:Dagger2注入ViewModel报错,需@Provides注解方法
解决Dagger2 ViewModel注入时的
Map<Class<ViewModel>, Provider<ViewModel>>缺失问题 这个错误的核心原因很明确:Dagger找不到用来构建Map<Class<? extends ViewModel>, Provider<ViewModel>>的绑定配置——这个Map是Dagger多绑定的核心,用来把各个ViewModel和它们的提供者关联起来,你的代码里肯定漏了关键的绑定步骤。
下面是一步步的修复方案:
1. 定义ViewModel的多绑定Key注解
先创建一个自定义的MapKey注解,用来标识每个ViewModel的类型,Dagger会用它来区分Map里的不同条目:
@MapKey @Target(AnnotationTarget.FUNCTION, AnnotationTarget.PROPERTY_GETTER, AnnotationTarget.PROPERTY_SETTER) @Retention(AnnotationRetention.RUNTIME) annotation class ViewModelKey(val value: KClass<out ViewModel>)
2. 绑定ViewModel到多绑定Map中
创建一个抽象的Dagger模块,用@Binds + @IntoMap + @ViewModelKey的组合,把每个ViewModel绑定到Map里:
@Module abstract class ViewModelModule { // 替换成你自己的ViewModel类 @Binds @IntoMap @ViewModelKey(HomeViewModel::class) abstract fun bindHomeViewModel(viewModel: HomeViewModel): ViewModel // 如果有多个ViewModel,重复上面的绑定逻辑即可 @Binds @IntoMap @ViewModelKey(ProfileViewModel::class) abstract fun bindProfileViewModel(viewModel: ProfileViewModel): ViewModel }
注意:你的ViewModel类的构造函数必须加上
@Inject注解,否则Dagger无法创建它的实例。
3. 确保Component包含这个模块
把刚才的ViewModelModule添加到你的AppComponent(或者对应的子Component)的modules列表中:
@Singleton @Component(modules = [AndroidSupportInjectionModule::class, ViewModelModule::class, /* 其他模块 */]) interface AppComponent : AndroidInjector<YourApplication> { @Component.Factory interface Factory { fun create(@BindsInstance application: Application): AppComponent } }
4. 正确实现ViewModelFactory
你需要一个依赖这个Map的ViewModelFactory,并且让Dagger注入它:
class DaggerViewModelFactory @Inject constructor( // 这里必须加@JvmSuppressWildcards,否则Kotlin泛型和Dagger的Java泛型会不兼容 private val viewModels: Map<Class<out ViewModel>, @JvmSuppressWildcards Provider<ViewModel>> ) : ViewModelProvider.Factory { override fun <T : ViewModel> create(modelClass: Class<T>): T { val provider = viewModels[modelClass] ?: throw IllegalArgumentException("ViewModel class $modelClass not found in Dagger bindings") return provider.get() as T } }
常见的坑要注意
- 不要忘记给ViewModel的构造函数加
@Inject,否则Dagger无法提供它的Provider - Map的泛型必须加
@JvmSuppressWildcards,Kotlin的泛型通配符和Java处理方式不同,不加会导致Dagger无法识别绑定 - 确认你的Component确实包含了
ViewModelModule,如果是子Component,要确保父Component传递了必要的绑定
内容的提问来源于stack exchange,提问作者Simon Schiller
相关产品推荐
相关产品推荐

