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