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

Kotlin集成Dagger 2.15遇ViewModel注入错误:需@Provides注解方法

解决Dagger 2.15集成ViewModel时的编译异常问题

我来帮你搞定这个Dagger和ViewModel的注入坑!你遇到的这个编译错误,核心是Dagger找不到提供Map<java.lang.Class<? extends android.arch.lifecycle.ViewModel>,? extends javax.inject.Provider<android.arch.lifecycle.ViewModel>>的@Provides方法——这在ViewModel注入场景里是非常典型的疏漏,咱们一步步来修复:

1. 补全ViewModel绑定的核心注解和Module

首先你需要一个自定义的@ViewModelKey注解,用来标记ViewModel类作为Map的key:

@MapKey
@Target(AnnotationTarget.FUNCTION)
@Retention(AnnotationRetention.RUNTIME)
annotation class ViewModelKey(val value: KClass<out ViewModel>)

然后创建一个抽象的ViewModelModule,用@Binds + @IntoMap + @ViewModelKey的组合,把每个ViewModel绑定到Dagger的映射表中:

@Module
abstract class ViewModelModule {
    // 替换成你项目里的ViewModel类,比如RecipeViewModel
    @Binds
    @IntoMap
    @ViewModelKey(RecipeViewModel::class)
    abstract fun bindRecipeViewModel(viewModel: RecipeViewModel): ViewModel

    // 如果有其他ViewModel,同样添加对应的绑定方法
}

⚠️ 关键注意:这里的Module必须是抽象类,@Binds方法也要是抽象的,而且你的ViewModel构造函数必须加上@Inject注解,比如:

class RecipeViewModel @Inject constructor(
    private val recipeRepository: RecipeRepository
) : ViewModel() {
    // 你的ViewModel业务逻辑
}

2. 实现Dagger专属的ViewModelFactory

接下来需要一个ViewModelFactory,让Dagger把刚才的ViewModel映射表注入进来,供Activity/Fragment获取ViewModel:

class DaggerViewModelFactory @Inject constructor(
    private val viewModelMap: MutableMap<Class<out ViewModel>, Provider<ViewModel>>
) : ViewModelProvider.Factory {
    override fun <T : ViewModel> create(modelClass: Class<T>): T {
        val viewModelProvider = viewModelMap[modelClass] 
            ?: throw IllegalArgumentException("找不到对应的ViewModel类: $modelClass")
        return viewModelProvider.get() as T
    }
}

3. 关联ViewModelModule和Factory到Dagger Component

确保你的AppComponent(或者对应的ActivityComponent)包含了ViewModelModule,并且暴露ViewModelFactory的注入入口:

@Singleton
@Component(modules = [ViewModelModule::class, AndroidSupportInjectionModule::class, /*其他你的业务Module*/])
interface AppComponent {
    fun inject(app: YourApplication)
    
    // 暴露ViewModelFactory,供Activity注入使用
    fun viewModelFactory(): DaggerViewModelFactory
}

如果是用@ContributesAndroidInjector的方式管理Activity注入,可以在Activity的子Module里提供Factory:

@Module
class MainActivityModule {
    @Provides
    fun provideViewModelFactory(factory: DaggerViewModelFactory): ViewModelProvider.Factory {
        return factory
    }
}

4. 在Activity中注入并使用ViewModel

最后,在你的Activity里注入ViewModelFactory,并用它获取ViewModel:

class MainActivity : AppCompatActivity(), HasAndroidInjector {
    @Inject
    lateinit var viewModelFactory: ViewModelProvider.Factory
    private lateinit var recipeViewModel: RecipeViewModel

    override fun onCreate(savedInstanceState: Bundle?) {
        AndroidInjection.inject(this)
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_main)
        
        // 通过Dagger的Factory获取ViewModel
        recipeViewModel = ViewModelProvider(this, viewModelFactory)[RecipeViewModel::class.java]
    }

    // 实现HasAndroidInjector接口的要求
    @Inject
    lateinit var androidInjector: DispatchingAndroidInjector<Any>
    override fun androidInjector(): AndroidInjector<Any> = androidInjector
}

5. 检查依赖和注解处理器配置

最后确认你的Module级build.gradle里的依赖配置正确,尤其是kapt注解处理器:

// Dagger相关依赖
implementation 'com.google.dagger:dagger:2.15'
implementation 'com.google.dagger:dagger-android:2.15'
implementation 'com.google.dagger:dagger-android-support:2.15'
kapt 'com.google.dagger:dagger-compiler:2.15'
kapt 'com.google.dagger:dagger-android-processor:2.15'

// ViewModel相关依赖(对应你用的旧版Architecture Components)
implementation 'android.arch.lifecycle:extensions:1.1.1'
implementation 'android.arch.lifecycle:viewmodel-ktx:1.1.1'

⚠️ 注意:因为你用的是android.arch.lifecycle(旧版Android Architecture Components),请不要混用AndroidX的ViewModel依赖,否则会出现版本冲突。

按照这些步骤调整后,重新编译项目,那个缺少@Provides方法的错误应该就会消失了!

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.20 11:17:46