square / anvil

A Kotlin compiler plugin to make dependency injection with Dagger 2 easier.
Apache License 2.0
1.31k stars 82 forks source link

How to deal with MergeSubComponent with AndroidInjector #759

Closed wahyupermadie closed 11 months ago

wahyupermadie commented 1 year ago

Currently in my existing project, I mostly use SubComponent for feature-related Screens and also I use Android Injector. For example

Click Me TestScreenSubComponent ``` @ScreenScope @Subcomponent(modules = []) interface TestScreenComponent : AndroidInjector { @Subcomponent.Factory abstract class Builder : AndroidInjector.Factory { abstract override fun create(instance: TestScreen): TestScreenComponent } } ``` TestModule ``` @Module(subcomponents = [TestScreenComponent::class]) object TestModule { @Binds @IntoMap @ClassKey(TestScreen::class) fun provideTestScreenBuilder(builder: TestScreenComponent.Builder): AndroidInjector.Factory<*> } ``` And in AppModule, basically I'm just include the TestModule ``` @Module(includes = [TestModule::class, others dagger module]) object AppModule ```

I am just curious how to deal with @MergeSubComponent, currently I'm trying with ContributesSubComponent like this and this is works

Click Me TestScreenSubComponent ``` @ScreenScope @ContributesSubcomponent( scope = AppSubScope::class, parentScope = AppScope::class, ) interface TestScreenComponent : AndroidInjector { @Subcomponent.Factory abstract class Builder : AndroidInjector.Factory { abstract override fun create(instance: TestScreen): TestScreenComponent } } ``` TestModule ``` @ContributesTo(AppScope::class) @Module object TestModule { @Binds @IntoMap @ClassKey(TestScreen::class) fun provideTestScreenBuilder(builder: TestScreenComponent.Builder): AndroidInjector.Factory<*> } ``` And in AppComponent ``` @MergeComponent(AppScope::class) interface AppComponent ```

I have tried to use @MergeSubComponent but i got error on TestModule.provideTestScreenBuilder

 com.example.di.TestScreenComponent.Builder cannot be provided without an @Provides-annotated method.
Click Me TestScreenSubComponent ``` @ScreenScope @MergeSubComponent(AppSubScope::class) interface TestScreenComponent : AndroidInjector { @Subcomponent.Factory abstract class Builder : AndroidInjector.Factory { abstract override fun create(instance: TestScreen): TestScreenComponent } } ``` TestModule ``` @ContributesTo(AppScope::class) @Module object TestModule { @Binds @IntoMap @ClassKey(TestScreen::class) fun provideTestScreenBuilder(builder: TestScreenComponent.Builder): AndroidInjector.Factory<*> } ``` And in AppComponent ``` @MergeComponent(AppScope::class) interface AppComponent ```