How can I avoid to set all my component's modules in an activity to inject dependencies with Dagger 2?

117 Views Asked by At

I'm using Dagger 2 to inject dependencies and MVP as my application design pattern.

I have 2 activities(MainActivity and LoginActivity). Each one implements an interface (MainView and LoginView respectly) and have an associated module (LoginModule and MainModule). On the other hand, I have a MainComponent which uses the 2 modules. The problem is the following: If I'm trying to inject dependencies in MainActivity, I just need the MainModule, not the LoginModule, but the MainComponent uses the 2 modules in his graph. So, I have to set the 2 modules (correct me if I'm wrong), It should be something like this:

public void setupComponent(MyApplicationComponent appComponent){
   DaggerMainComponent.builder()
       .myApplicationComponent(appComponent)
       .mainModule(new MainModule(this))
       .loginModule(new LoginModule(???))
       .build.inject(this);
}

When I inject dependencies in MainActivity I just need to set the MainModule and in LoginActivity the LoginModule, not both. How can I do it?

LoginModule:

@Module
public class LoginModule {

    private LoginView loginView;

    public LoginModule(LoginView view) {
        loginView = view;
    }

    @Provides
    public LoginView provideLoginView() {
        return loginView;
    }

MainModule:

@Module
public class MainModule {
    private MainView mainView;

    public MainModule(MainView mainView){
        this.mainView=mainView;
    }

    @Provides MainView provideMainView(){
        return mainView;
    }
}

As you can see MainModule and LoginModule, both have one parameter in their constructors (MainView and LoginView). So knowing that MainActivity implements MainView and LoginModule implements LoginView, If I'm in MainActivity and I want to inject dependencies I need to set MainModule like this: .mainModule(new MainModule(this)).build.inject(this). But what about LoginModule? How can I avoid to set it in this activity without having to remove it from MainComponent's modules? or how can I set it (I can't use "THIS" in .loginModule(new LoginModule(this)) because of MainActivity implements MainView but not LoginView)?

MainComponent:

@ActivityScope
@Component(
        dependencies = MyApplicationComponent.class,
        modules = {LoginModule.class, MainModule.class}
)

public interface MainComponent {
    void inject(LoginActivity loginActivity);
    void inject(MainActivity mainActivity);
    LoginPresenterImp getLoginPresenter();
    MainPresenterImp getMainPresenter():
}

Thanks in advance.

1

There are 1 best solutions below

0
On BEST ANSWER

LoginModule and MainModule should have their own components.

I would suggest making a LoginComponent and a MainComponent and then adding them to MyApplicationComponent as subcomponents.

@ApplicationScope
@Component(
    modules = {ApplicationModule.class})
public interface ApplicationComponent {

    void inject(Application application);

    MainComponent plus(MainModule mainModule);
    LoginComponent plus(LoginModule loginModule);

}

////

@ActivityScope
@Subcomponent(
    modules = {
            MainModule.class,
    }
)
public interface MainComponent {

    void inject(MainActivity mainActivity);

}

////

@ActivityScope
@Subcomponent(
    modules = {
            LoginModule.class,
    }
)
public interface LoginComponent {

    void inject(LoginActivity loginActivity);

}

then to inject your activities

public void setupComponent(ApplicationComponent appComponent){
appComponent.plus(new MainModule(this)).inject(this)
}

public void setupComponent(ApplicationComponent appComponent){
appComponent.plus(new LoginModule(this)).inject(this)
}