Testing Here
Testing Here

Reputation: 185

How to inject same Dagger 2 dependency with different implementations based on the Context?

I have a Dagger 2 dependency that is provided differently if it’s an Activity or some other context instance (e.g., a Service). Both would refer to the same interface but their implementation varies. How could I organise this using Dagger 2?

Right now, I’m trying with two different components, ActivityComponent and ContextComponent with their respective modules as follows:

@ActivityScope        
@Subcomponent(            
  modules = {                
    ActivityModule.class,                
    ContextModule.class
  })        
public interface ActivityComponent {
}

@Module    
public class ActivityModule {

    @Provides
    @MyActivityQualifier
    public MyObject provideMyObject() {
    }
}


@ContextScope
@Subcomponent(        
  modules = {
    ContextModule.class
  })    
public interface ContextComponent {    }

@Module
public class ContextModule.class {

    @Provides
    public MyObject provideMyObject() {
    }
} 

Then, if I’m using MyObject in an Activity, I have to add the qualifier as follows:

@Inject @MyActivityQualifier MyObject myObject; 

This feels wrong but I’m not sure why. Is there a better way?

Upvotes: 3

Views: 1469

Answers (1)

David Medenjak
David Medenjak

Reputation: 34532

You are using subcomponents.
The question is: Can or should both objects be "visible" (usable, injectable, ...) at the same time?

  • Yes: You will have to use some sort of qualifier. Or else you can't distinguish them.
  • No: You can "hide" them by not exposing the dependency from the dependent component. You would have to use a normal component instead of @Subcomponent in this case, and just don't add the getMyInterface() method to your parent component.

And there aren't any other options, because you have 2 components dependent on each other. So your approach looks fine with the information you provide.

Note you can also just qualify one of your implementations. In my project, I use a qualified @Named("public") annotation for a common implementation without user data. If I don't add any qualifier I will just get the other one (unqualified).


With independent components, e.g. ActivityAComponent and ActivityBComponent you could just switch which implementation gets provided using different modules.

Upvotes: 1

Related Questions