I'm having trouble injecting a fragment that I contribute via @ContributesAndroidInjector.
I'm trying to build a hierarchy within modules (features). Basically, what I have is:
My AppComponent depends on CoreComponent:
@Singleton
@Component(modules = [CoreModule::class])
interface CoreComponent {
fun getApp(): Application
@Component.Factory
interface Factory {
fun create(@BindsInstance app: Application): CoreComponent
}
}
And initialize as:
@AppScope
@Component(
modules = [
AndroidInjectionModule::class,
ActivityContributor::class,
AppModule::class],
dependencies = [CoreComponent::class]
)
interface AppComponent : AndroidInjector<App> {
@Component.Factory
interface Factory {
fun create(component: CoreComponent): AppComponent
}
}
This part is pretty much straightforward. AppComponent has ActivityContributor which only has one @ContributesAndroidInjector, which is MainActivity.
Now, problem starts when I want to add an encapsulated feature subcomponent. Assume I have two fragments FragmentOne and FragmentTwo in my feature, with some common dependencies as well as their own.
What I want to have is a FeatureSubcomponent which has FeatureModule and FeatureContributor:
@FeatureScope
@Subcomponent(
modules = [FeatureContributor::class,
FeatureModule::class
]
)
abstract class FeatureSubcomponent {
@Subcomponent.Factory
interface Factory {
fun create(): FeatureSubcomponent
}
}
While FeatureModule has dependencies common for both fragments, FeatureContributor is contributing FragmentOne and FragmentTwo with their own modules:
@Module
abstract class FeatureContributor {
@ContributesAndroidInjector(modules = [FeatureOneModule::class])
abstract fun featureOneFragment(): FeatureOneFragment
@ContributesAndroidInjector(modules = [FeatureTwoModule::class])
abstract fun featureTwoFragment(): FeatureTwoFragment
}
And of course, I add FeatureSubcomponent as a subcomponent to AppModule:
@Module(subcomponents = [FeatureSubcomponent::class])
And if you scroll up, you'll see AppModule is included in modules of AppComponent.
Problem is, while it's compiling and running, it crashes once it reaches to any feature fragments due to No injector factory bound for error.
Roughly summarising my structure:
Anyone has ideas about why or how it should be instead or am I missing something ?
Edit
Here's the diagram I prepared to make it easier to understand hierarchy

Dagger android does injection by finding the closest injector in the current scope. For Fragment, it is the containing Activity and for Activity it is the Application instance.
When you call AndriodInject.inject(this) in the Fragment it is goes up the hierarchy to find injector and then injects the Fragment.
Have you extended DaggerAppCompatActivity/implemented the HasFragmentInjector?
Another thing I see is, why create subcomponent again when @ContributesAndroidInjector already creates a sub component internally for you?
@ContributesAndroidInjector.modules is a way for talking to the generated subcomponent. So the relationship between Activity and FeatureFragment must be established in the subcomponent that the @ContributesAndroidInjector will be generating.
Right now your hierarchy is like this since you have deliberately specified FeatureSubComponent to be subcomponent of the AppComponent
App -> FeatureSubComponent -> [A, B] (generated)
\
\---> MainActivitySubcomponent (generated by contributesAndroidInjector).
What you actually need is:
App -> MainActivitySubComponent (generated) -> [Feature A , Feature B] (generated)
To do this
@ContributesAndroidInjector(modules = [FeatureContributor::class])
abstact fun mainActivity() : MainActivity
Feature contributor can have @ContributesAndroidInjectors inside. When Dagger compiler sees that FeatureContributor has @ContributesAndroidInjectors, it makes the subcomponent generated by those to be the subcomponent of the activity since it is the parent.
Which basically means Activity -> Fragment hierarchy.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With