Dagger Multi Module -- ViewModelProvider.Factory cannot be provided without an @Provides-annotated method

642 Views Asked by At

I am working on applying the multi module structure with dagger to my project. I am getting error while working on ViewModelFactory. What I actually want to do for the ViewModelFactory is this: I want to have the app module provide the ViewModelFactory and have the feature modules use it.

The error I encountered here is:

C:\Users\Cloud\Desktop\daggerMultiModuleSample\DaggerMultiModuleSample\feature-one\build\tmp\kapt3\stubs\debug\com\emrememil\feature_one\di\FeatureOneComponent.java:8: error: [Dagger/MissingBinding] androidx.lifecycle.ViewModelProvider.Factory cannot be provided without an @Provides-annotated method.
public abstract interface FeatureOneComponent {
                ^
      androidx.lifecycle.ViewModelProvider.Factory is injected at
          com.emrememil.feature_one.view.FeatureOneActivity.viewModelFactory
      com.emrememil.feature_one.view.FeatureOneActivity is injected at
          com.emrememil.feature_one.di.FeatureOneComponent.inject(com.emrememil.feature_one.view.FeatureOneActivity)

AppComponent.kt

@AppScope
@Component(
    dependencies = [MainComponent::class],
    modules = [AppModule::class, ViewModelModule::class]
)
interface AppComponent {
    /**
     * Inject dependencies on application.
     *
     * @param application The sample application.
     */
    fun inject(application: SampleApp)
}

AppModule.kt

@Module
class AppModule {
    /**
     * Create a provider method binding for [Context].
     *
     * @param application Sample Application.
     * @return Instance of context.
     * @see Provides
     */
    @Provides
    fun provideContext(application: SampleApp): Context = application.applicationContext
}

ViewModelModule.kt

@Module
abstract class ViewModelModule {
    @Binds
    abstract fun bindViewModelFactory(factory: ViewModelFactory): ViewModelProvider.Factory

    @Binds
    @IntoMap
    @ViewModelKey(FeatureOneViewModel::class)
    abstract fun bindFeatureOneViewModel(featureOneViewModel: FeatureOneViewModel): ViewModel
}

ViewModelFactory.kt

@Suppress("UNCHECKED_CAST")
class ViewModelFactory @Inject constructor(
    private val creators: @JvmSuppressWildcards Map<Class<out ViewModel>, Provider<ViewModel>>
) : ViewModelProvider.Factory {

    override fun <T : ViewModel> create(modelClass: Class<T>): T {
        val found = creators.entries.find { modelClass.isAssignableFrom(it.key) }
        val creator = found?.value
            ?: throw IllegalArgumentException("unknown model class $modelClass")
        try {
            @Suppress("UNCHECKED_CAST")
            return creator.get() as T
        } catch (e: Exception) {
            throw RuntimeException(e)
        }
    }
}

FeatureOneComponent.kt

@FeatureScope
@Component(
    dependencies = [MainComponent::class],
    modules = [FeatureOneModule::class]
)
interface FeatureOneComponent {
    fun inject(activity: FeatureOneActivity)
}

FeatureOneActivity.kt

@Inject
lateinit var viewModelFactory: ViewModelProvider.Factory

@Inject
lateinit var viewModel: FeatureOneViewModel

override fun onCreate(savedInstanceState: Bundle?) {
    super.onCreate(savedInstanceState)
    setContentView(R.layout.activity_feature_one)

    DaggerFeatureOneComponent
        .builder()
        .mainComponent(InjectUtils.provideAppComponent(applicationContext))
        .build()
        .inject(this)
}
0

There are 0 best solutions below