I am trying to create dependent components for Activity
and Fragment
. Here's my Activity Component:
@Component(modules = [ActivityModule::class],
dependencies = [AppComponent::class])
interface ActivityComponent{
fun inject(activity: Activity)
@Component.Builder
interface Builder{
fun appComponent(component: AppComponent): Builder
fun activityModule(activityModule: ActivityModule): Builder
fun build(): ActivityComponent
}
}
@Module
class ActivityModule(private val activity: Activity) {
@Provides
fun provideActivity() = activity
}
Fragment Component:
@Component(modules = [FragmentModule::class],
dependencies = [ActivityComponent::class])
interface FragmentComponent{
fun inject(fragment: Fragment)
@Component.Builder
interface Builder{
fun activityComponent(activityComponent: ActivityComponent): Builder
fun fragmentModule(fragmentModule: fragmentModule): Builder
fun build(): FragmentComponent
}
}
@Module
class FragmentModule(private val fragment: Fragment) {
@Provides
fun provideFragment() = fragment
}
I am getting a compile error in places where I am trying to access activity.
Activity cannot be provided without an @Provides-annotated method.
It's my understanding that since Activity
has already been injected in the ActivityComponent
, and Fragment
is simply adding itself to the ActivityComponent
, it should get all the dependencies provided by ActivityComponent
and AppComponent
's modules. I see this happening in ActivityComponent
, where I get dependencies from AppComponent
automatically.
Update:
If I add the following code to the FragmentModule
, I am able to get the code compiled:
@Provides
fun provideActivity() = fragment.context as Activity
But this is not making sense to me, as I was hoping to get the pre-injected Activity
from ActivityComponent
I realized that parent components should always declare the dependencies they want to expose. Otherwise dependent components cannot access them just by declaring them as dependents. Note that transitive dependencies don't work either. So AppComponent
has to declare a dependency for ActivityComponent
to use it - but ActivityComponent
has to re-declare the same dependency if FragmentComponent
needs it.
interface ActivityComponent{
fun inject(activity: Activity)
@Component.Builder
interface Builder{
fun appComponent(component: AppComponent): Builder
fun activityModule(activityModule: ActivityModule): Builder
fun build(): ActivityComponent
}
var activity: Activity
}