I've written a small app which uses dagger2 for injecting dependencies. Everything was working great (last year), but now, after +6 months, it seems like the app simply stopped working after migrating Android Studio+gradle+kotlin plugin.
After migrating, whenever I try to run the app, I end up with the following error:
e: D:\code\work\GESAndroid\app\build\tmp\kapt3\stubs\debug\pt\gov\madeira\newsapp\di\AppComponent.java:8: error: [Dagger/MissingBinding] java.util.Map<java.lang.Class<? extends android.arch.lifecycle.ViewModel>,javax.inject.Provider<android.arch.lifecycle.ViewModel>> cannot be provided without an @Provides-annotated method.
public abstract interface AppComponent extends dagger.android.AndroidInjector<pt.gov.madeira.newsapp.MyApp> {
^
java.util.Map<java.lang.Class<? extends android.arch.lifecycle.ViewModel>,javax.inject.Provider<android.arch.lifecycle.ViewModel>> is injected at
pt.gov.madeira.newsapp.di.viewmodels.ViewModelFactory(viewModels)
pt.gov.madeira.newsapp.di.viewmodels.ViewModelFactory is injected at
pt.gov.madeira.newsapp.di.viewmodels.ViewModelModule.bindViewModelFactory$app_debug(factory)
android.arch.lifecycle.ViewModelProvider.Factory is injected at
pt.gov.madeira.newsapp.ui.main.MainActivity.viewModelFactory
pt.gov.madeira.newsapp.ui.main.MainActivity is injected at
dagger.android.AndroidInjector.inject(T) [pt.gov.madeira.newsapp.di.AppComponent ? pt.gov.madeira.newsapp.di.ActivityBindingModule_MainActivity$app_debug.MainActivitySubcomponent]
The following other entry points also depend on it:
dagger.android.AndroidInjector.inject(T) [pt.gov.madeira.newsapp.di.AppComponent ? pt.gov.madeira.newsapp.di.ActivityBindingModule_ShowDetailsActivity$app_debug.ShowDetailsActivitySubcomponent]
Now, can someone please help translate the error? It seems like it's complaining about ViewModel injection, but I'm not sure on why this is happening.
Btw, here's the code I was using to inject the view models:
class ViewModelFactory @Inject constructor(
private val viewModels: @JvmSuppressWildcards Map<Class<out ViewModel>, Provider<ViewModel>>
) : ViewModelProvider.Factory {
override fun <T : ViewModel?> create(modelClass: Class<T>): T
= viewModels[modelClass]?.get() as T
}
@Module
abstract class ViewModelModule {
@Binds
internal abstract fun bindViewModelFactory(factory: ViewModelFactory): ViewModelProvider.Factory
}
And here's the activity binding code:
@Module
abstract class ActivityBindingModule {
@ActivityScoped
@ContributesAndroidInjector(modules = [MainActivityModule::class])
internal abstract fun mainActivity(): MainActivity
@ActivityScoped
@ContributesAndroidInjector(modules = [ShowDetailsModule::class])
internal abstract fun showDetailsActivity(): ShowDetailsActivity
}
And here's the activity's injection code:
@Module
abstract class ShowDetailsModule {
@Binds
@IntoMap
@ViewModelKey(ShowDetailsViewModel::class)
abstract fun bindShowDetaislViewModel(viewModel: ShowDetailsViewModel): ViewModel
}
@Module
abstract class MainActivityModule {
@Binds
@IntoMap
@ViewModelKey(MainActivityViewModel::class)
internal abstract fun bindMainActivityViewModel(viewModel: MainActivityViewModel): ViewModel
}
And finally, here's the code for the attributes:
@Documented
@Scope
@Retention(RetentionPolicy.RUNTIME)
annotation class ActivityScoped
@Target(AnnotationTarget.FUNCTION, AnnotationTarget.PROPERTY_GETTER, AnnotationTarget.PROPERTY_SETTER)
@Retention(AnnotationRetention.RUNTIME)
@MapKey
annotation class ViewModelKey (val value: KClass<out ViewModel>) {
}
So, can anyone point me in the right direction?
Thanks.