@Module.subcomponents on Android

I have the following (simplified) setup of 1 Application and 1 Activity, 1 Parent Component and 1 Subcomponent:

Application:

public class ExampleApp extends Application {
    private AppComponent component;

    @Override
    public void onCreate() {
        super.onCreate();

        component = DaggerAppComponent.create();
    }

    public AppComponent getAppComponent() {
        return component;
    }
}

AppComponent:

@Singleton
@Component(modules = AppModule.class)
public interface AppComponent {

    ActivityComponent.Builder getActivityComponentBuilder();
}

Activity Subcomponent:

@PerActivity
@Subcomponent(modules = {ActivityModule1.class, ActivityModule2.class})
public interface ActivityComponent {

    void inject(MainActivity mainActivity);


    @Subcomponent.Builder
    interface Builder {

        @BindsInstance
        Builder binding1(@Named("binding1") int binding1);

        @BindsInstance
        Builder binding2(@Named("binding2") int binding2);

        ActivityComponent build();
    }
}

MainActivity:

public class MainActivity extends AppCompatActivity {
    @Inject
    TheObjectIWant theObjectIWant1, theObjectIWant2;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        ActivityComponent component = ((ExampleApp) getApplication()).getAppComponent()
                .getActivityComponentBuilder()
                .binding1(100)
                .binding2(200)
                .build();

        component.inject(this);

        theObjectIWant1.doStuff();
        theObjectIWant2.doStuff();
    }
}

I would now like to refactor this same example to use the Module.subcomponents attribute instead of the Subcomponent.Builder factory method.
For this, I remove getActivityComponentBuilder() from the AppComponent and add the Module.subcomponents attribute to the AppModule:

AppComponent (new):

@Singleton
@Component(modules = AppModule.class)
public interface AppComponent {

}

AppModule (new):

@Module(subcomponents = ActivityComponent.class)
public abstract class AppModule {
    [...]
}

My question is pretty simple. How do I now get the ActivityComponent.Builder into the MainActivity? I can’t constructor inject the MainActivity, so there’s only really field injection left:

MainActivity (new, theory):

public class MainActivity extends AppCompatActivity {
    @Inject
    ActivityComponent.Builder activityComponentBuilder
    @Inject
    TheObjectIWant theObjectIWant1, theObjectIWant2;

    ((ExampleApp) getApplication()).getAppComponent().inject(this)
    [...]
}

But this will not work, since the AppComponent can’t inject theObjectIWant1 and theObjectIWant1. They only come from the ActivityComponent.

So is this approach just not suitable here? Since this is more of a theoretical question, please ignore dagger.android here and assume we want to handle this without it.

Leave a Reply

avatar
  Subscribe  
Notify of