Dagger 2 Android: inject the scoped activity

Viewed 946

I'm using Dagger Android to link dependencies in my Android application. I have 2 Activities, both have their own Scope (@ActivityScoped). Here is my code so far :

MyApplication.java

public class MyApplication extends Application implements HasActivityInjector {
    @Inject DispatchingAndroidInjector<Activity> activityDispatchingAndroidInjector;

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

        DaggerAppComponent.builder()
                .application(this)
                .build()
                .inject(this);
    }

    @Override
    public AndroidInjector<Activity> activityInjector() {
        return activityDispatchingAndroidInjector;
    }
}

AppComponent.java

@Singleton
@Component(modules = {
        AndroidInjectionModule.class,
        AppModule.class,
        ActivityBindingModule.class
})
public interface AppComponent {

    @Component.Builder
    interface Builder {
        @BindsInstance
        Builder application(Application app);

        AppComponent build();
    }

    void inject(MyApplication app);
}

ActivityBindingsModule.java

@Module(subcomponents = ActivityComponent.class)
public abstract class ActivityBindingModule {

    @ActivityScoped
    @ContributesAndroidInjector
    public abstract MainActivity contributeMainActivityInjector();

    @ActivityScoped
    @ContributesAndroidInjector
    public abstract SecondActivity contributeSecondActivityInjector();
}

Let's say I have a class MyClass tied to ActivityScoped that I want to inject into both Activities :

MyClass.java

@ActivityScoped
public class MyClass {

    @Inject
    public MyClass(Activity activity) {
        // Do something with the activity instance...
    }
}

What I want to achieve is to inject into MyClass the Activity instance of the enclosing scope. For example, if MyClass is injected into ActivityA, then the activity constructor argument of MyClass should be an instance of ActivityA.

What I tried :

  • @Binds annotated method to inject ActivityA and ActivityB as Activity. This doesn't work since Dagger does not allow binding multiple implementations to the same base type.
  • Map Multibindings doesn't suit my needs : I don't want MyClass to know about the Activity in which it is injected.

Maybe I'm missing something, as dependency injection is rather hard to setup. How can I do that with Dagger Android ?

1 Answers

@Binds annotated method to inject ActivityA and ActivityB as Activity. This doesn't work since Dagger does not allow binding multiple implementations to the same base type.

That's the right way to do so. You only get an error when you try to bind multiple implementations to the same type in the same component. So you should not bind both within your AppComponent, but to the @ActivityScoped subcomponents.

You have to create a module for each Activity, A and B, that binds the implementation to Activity. Then you just add that module to the Subcomponent that Dagger creates for you.

@ActivityScoped
@ContributesAndroidInjector(modules={MainActivityBindingsModule.class})
public abstract MainActivity contributeMainActivityInjector();

That way the binding only exists within the @ActivityScoped component and you should be able to repeat it.

Related