'Error with injecting view model using Dagger 2

I just started learning Dagger 2 and trying to make subcomponent for subcomponent. I faced error and can't find where it comes from. Below I will write my dagger structure.

AppComponent
-AppModule
-SubcomponentsModule
--MainComponent
---MainModule
----AuthorizationComponent
-----AuthorizationModule
----UserProfileComponent
-----UserProfileModule
---ViewModelModule
-NetworkModule 

Application component:

@Singleton
@Component(modules = [AppModule::class, SubcomponentsModule::class, NetworkModule::class])
interface AppComponent {

    fun mainComponent(): MainComponent.Factory
}

It has SubcomponentsModule with one subcomponent so far:

@Module(subcomponents = [MainComponent::class])
class SubcomponentsModule

MainComponent:

@Subcomponent(modules = [MainModule::class, ViewModelModule::class])
interface MainComponent {

    @Subcomponent.Factory
    interface Factory {

        fun create(): MainComponent
    }

    fun inject(activity: MainActivity)

    fun authorizationComponent(): AuthorizationComponent.Factory

    fun userProfileComponent(): UserProfileComponent.Factory
}

ViewModelModule:

@Module
abstract class ViewModelModule {

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

MainComponent has MainModule with AuthorizationComponent and UserProfileComponent:

@Module(subcomponents = [AuthorizationComponent::class, UserProfileComponent::class])
abstract class MainModule {

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

AuthorizationComponent with AuthorizationModule:

@Subcomponent(modules = [AuthorizationModule::class])
interface AuthorizationComponent {

    @Subcomponent.Factory
    interface Factory {

        fun create(): AuthorizationComponent
    }

    fun inject(fragment: AuthorizationFragment)
}

AuthorizationModule:

@Module
abstract class AuthorizationModule {

    @Binds
    @IntoMap
    @ViewModelKey(AuthorizationViewModel::class)
    abstract fun authorizationViewModel(viewModel: AuthorizationViewModel): ViewModel
}

UserProfileComponent with UserProfileModule is equivalent to AuthorizationComponent and AuthorizationModule.

When I launch build, I get error:

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
          ui.base.ViewModelFactory(viewModels)
      ui.base.ViewModelFactory is injected at
          di.main.ViewModelModule.bindViewModelFactory(factory)
      androidx.lifecycle.ViewModelProvider.Factory is injected at
          ui.base.BaseActivity.viewModelFactory
      ui.main.MainActivity is injected at
          di.main.MainComponent.inject(ui.main.MainActivity) [di.AppComponent ? di.main.MainComponent]
The following other entry points also depend on it:
      di.main.auth.AuthorizationComponent.inject(ui.auth.AuthorizationFragment) [di.AppComponent ? di.main.MainComponent ? di.main.auth.AuthorizationComponent]
      di.main.userprofile.UserProfileComponent.inject(ui.userprofile.UserProfileFragment) [di.AppComponent ? di.main.MainComponent ? di.main.userprofile.UserProfileComponent]

The annotation I use for view models search is:

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

And the last thing that should be mentioned here is my ViewModelFactory:

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

    @Suppress("UNCHECKED_CAST")
    override fun <T : ViewModel> create(modelClass: Class<T>): T = viewModels[modelClass]?.get() as T
}


Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source