Reputation: 29260
In my app I have a component with Application scope (same as Singleton) that provides a ViewModel Factory, and a dependent component with Activity scope that injects the factory in a fragment.
The application component is defined as follows:
@Component(modules = [AppModule::class, /* other stuff */, ViewModelModule::class])
@ApplicationScope
interface AppComponent {
fun inject(app: Application)
/* other stuff */
val viewModelFactory: ViewModelFactory
}
The view model module is defined as follows:
@ApplicationScope
@Module
abstract class ViewModelModule {
@Binds
abstract fun bindViewModelFactory(viewModelFactory: ViewModelFactory): ViewModelProvider.Factory
@Binds
@IntoMap
@ViewModelKey(DisplayEntryViewModelImpl::class)
abstract fun bindDisplayEntryViewModel(displayEntryViewModelImpl: DisplayEntryViewModelImpl): ViewModel
}
The activity scope component is defined as follows:
@Component(dependencies = [AppComponent::class], modules = [DisplayEntryActivityModule::class])
@ActivityScope
interface DisplayEntryActivityComponent {
fun inject(displayEntryActivity: DisplayEntryActivity)
fun inject(displayEntryFragment: DisplayEntryFragment)
}
When I try to inject the viewmodel factory in the fragment I get this error:
error: android.arch.lifecycle.ViewModelProvider.Factory cannot be provided without an @Provides- or @Produces-annotated method.
If I update the activity component to include the view model module, like this
@Component(dependencies = [AppComponent::class], modules = [DisplayEntryActivityModule::class, ViewModelModule::class])
@ActivityScope
interface DisplayEntryActivityComponent {
fun inject(displayEntryActivity: DisplayEntryActivity)
fun inject(displayEntryFragment: DisplayEntryFragment)
}
Then it compiles. My understanding is that dependent components have access to the injected members from the parent component if the parent component explicitly provides those members, as I do here with the
val viewModelFactory: ViewModelFactory
so why do I still need to provide the viewmodel module in the activity scope component?
Upvotes: 2
Views: 647
Reputation: 351
When using dependencies, dagger will use that component to inject member.
Parent component must explicitly declare objects which can be used in child components.
@Component(modules = [AppModule::class, /* other stuff */, ViewModelModule::class])
@ApplicationScope
interface AppComponent {
fun inject(app: Application)
fun viewModelFactory(): ViewModelProvider.Factory
fun viewModel(): ViewModel
}
You can take a look at this article: https://proandroiddev.com/dagger-2-part-ii-custom-scopes-component-dependencies-subcomponents-697c1fa1cfc
Upvotes: 3