注入ViewModels时出现Dagger MissingBinding错误

时间:2019-05-21 15:29:04

标签: android kotlin dagger-2 android-architecture-components android-viewmodel

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

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)
}

AppModule:

@Module
class AppModule {

    @Inject
    lateinit var app: Application

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

ActivityModule:

@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
}

ViewModelFactory:

@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 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) {

MainActivity:

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)

2 个答案:

答案 0 :(得分:1)

我在合并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

答案 1 :(得分:0)

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

花了一些时间在互联网上之后,我发现了以下对我有用的解决方案。

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

@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