注入 ViewModel 时出现 Dagger MissingBinding 错误

Dagger MissingBinding error when injecting ViewModels

我是 dagger 的新手,想用它来注入 ViewModel(以及其他对象,例如存储库)。当我尝试编译应用程序时显示此错误:

e: C:\Project\...\app\build\tmp\kapt3\stubs\debug\com\myapp\di\AppComponent.java:16: error: [Dagger/MissingBinding] java.util.Map<java.lang.Class<? extends androidx.lifecycle.ViewModel>,javax.inject.Provider<androidx.lifecycle.ViewModel>> cannot be provided without an @Provides-annotated method.

public abstract interface AppComponent {
                ^
      java.util.Map<java.lang.Class<? extends androidx.lifecycle.ViewModel>,javax.inject.Provider<androidx.lifecycle.ViewModel>> is injected at
          com.myapp.di.ViewModelFactory(viewModels)
      com.myapp.di.ViewModelFactory is injected at
          com.myapp.di.ViewModelModule.bindViewModelFactory(factory)
      androidx.lifecycle.ViewModelProvider.Factory is injected at
          com.myapp.ui.activity.MainActivity.viewModelFactory
      com.myapp.ui.activity.MainActivity is injected at
          dagger.android.AndroidInjector.inject(T) [com.myapp.di.AppComponent ? com.myapp.di.ActivityModule_ContributeMainActivity.MainActivitySubcomponent]
  The following other entry points also depend on it:
      dagger.android.AndroidInjector.inject(T) [com.myapp.di.AppComponent ? com.myapp.di.ActivityModule_ContributeItemsFrament.ItemsFragmentSubcomponent]

也许有一个愚蠢的错误阻止了编译。

匕首组件:

@Singleton
@Component(modules = [AndroidSupportInjectionModule::class, AppModule::class, DatabaseModule::class, ViewModelModule::class, ActivityModule::class])
interface AppComponent {

    @Component.Builder
    interface Builder {
        @BindsInstance
        fun application(application: MyCustomApplication): Builder

        fun build(): AppComponent
    }

    fun inject(app: MyCustomApplication)
}

应用模块:

@Module
class AppModule {

    @Inject
    lateinit var app: Application

    @Provides
    @Singleton
    fun provideAppContext(): Context = app.applicationContext
}

活动模块:

@Module
abstract class ActivityModule {

    @ContributesAndroidInjector
    abstract fun bindMainActivity(): MainActivity

    @ContributesAndroidInjector
    abstract fun contributeMainFrament(): MainFragment
}

ViewModelModule:

@Module
abstract class ViewModelModule {

    @Binds
    abstract fun bindViewModelFactory(factory: ViewModelFactory): ViewModelProvider.Factory

    @Binds
    @IntoMap
    @ViewModelKey(MainViewModel::class)
    abstract fun mainViewModel(mainViewModel: MainViewModel): ViewModel
}

视图模型工厂:

@Singleton
class ViewModelFactory
@Inject constructor(private val viewModels: MutableMap<Class<out ViewModel>, Provider<ViewModel>>)
: ViewModelProvider.Factory {

    override fun <T : ViewModel> create(modelClass: Class<T>): T {
        val creator = viewModels[modelClass]
                ?: viewModels.asIterable().firstOrNull { modelClass.isAssignableFrom(it.key) }?.value
                ?: throw IllegalArgumentException("unknown model class $modelClass")
        return try {
            creator.get() as T
        } catch (e: Exception) {
            throw RuntimeException(e)
        }
    }
}

申请class:

class MyCustomApplication : Application(), HasActivityInjector, HasSupportFragmentInjector {

    @Inject lateinit var activityInjector: DispatchingAndroidInjector<Activity>

    override fun onCreate() {
        super.onCreate()

        DaggerMainComponent
                .builder()
                .application(this)
                .build()
                .inject(this)
    }

    override fun activityInjector() = activityInjector
}

MainViewModel(请注意,它从 AndroidViewModel 扩展并且需要应用程序上下文):

class MainViewModel @Inject constructor(app: Application, private val repository: MainRepository)
    : AndroidViewModel(app) {

主要活动:

class MainActivity : BaseActivity() {

    @Inject
    internal lateinit var viewModelFactory: ViewModelProvider.Factory
    private lateinit var viewModel: MainViewModel

    override fun onCreate(savedState: Bundle?) {
        AndroidInjection.inject(this)
        super.onCreate(savedState)
        viewModel = ViewModelProviders.of(this,viewModelFactory).get(MainViewModel::class.java)

我在组合 Android XKotlin version 1.3.0 时遇到了同样的问题,Dagger 将无法创建 MultiBindings。为了解决这个问题,我只是按照以下步骤操作:

a) build.gradle 文件上的 Kotlin 版本更新到 1.3.31

dependencies {
    classpath "org.jetbrains.kotlin:kotlin-gradle-plugin: 1.3.31"
}

b) 清理并重建 项目,为此,在终端中执行以下命令:

$ gradle clean build 

或者如果使用 gradle 包装器:

 $ ./gradlew clean build

我已经尝试将 kotlin-gradle-plugin 更新为 1.3.31,但它对我不起作用。

在网上花了一些时间后,我找到了以下适合我的解决方案。

尝试在 Provider<ViewModel> 之前添加 @JvmSuppressWildcards,如下所示:

@Singleton
@Provides
fun provideViewModelFactory(creators: Map<Class<out ViewModel>, @JvmSuppressWildcards Provider<ViewModel>>): ViewModelFactory {
    return ViewModelFactory(creators)
}

还有ViewModelFactory

class ViewModelFactory(private val creators: Map<Class<out ViewModel>, @JvmSuppressWildcards Provider<ViewModel>>) :
        ViewModelProvider.Factory