I'm new to dagger and want to use it for injecting ViewModels (along with other objects such as repositories). When I try to compile the app this error is shown:
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]
Maybe there is one silly mistake that prevents compilation.
Dagger component:
@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)
}
}
}
The application 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 (note that it extends from AndroidViewModel
and requires an application context):
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)
I faced same issue combining Android X
and Kotlin version 1.3.0
, Dagger won't be able to create MultiBindings
. To solve the problem I just followed next steps:
a) Update Kotlin version to 1.3.31 on build.gradle
file:
dependencies {
classpath "org.jetbrains.kotlin:kotlin-gradle-plugin: 1.3.31"
}
b) Clean and rebuild the project, to do so, execute the following command in a terminal:
$ gradle clean build
or if using gradle wrapper:
$ ./gradlew clean build