Search code examples
dagger-2dagger

Can dagger provide different implementations of the interface, depending on requested type?


I just started to learn Dagger and I wonder: Can it provide different implementations of the interface, depending on the request? For example, I have an interface Api and I have 2 implementations of this interface - TwitterApi and FacebookApi. Can I write something like the following?

@Provides
Api provideApi(ApiType type) {
    switch (type){
        case TWITTER_API:
            return new TwitterApi();
        case FACEBOOK_API:
            return new FacebookApi();
    }
}

Maybe @Named() can help somehow?


Solution

  • This really depends on what you are trying to accomplish. You have 2 basic setups, whether you want to access your different implementations at once, or just want to supply one.

    Access them at the same time / within the same scope

    This is where you want to use a @Qualifier, e.g. @Named. It lets you define 2 qualified objects of the same type, so you could request / use both at the same time within the same module.

    Here you just put a qualifier on both your implementations, and can provide & request both at the same time.

    @Binds
    @Qualifier("twitter")
    Api provideApi(TwitterApi api);
    

    And request with

    @Inject @Qualifier("twitter") Api api;
    

    Use a single one within a scope

    In case that you have some ApiDependentThing that takes one of your Api implementations and you want to either provide TwitterApi or FacebookApi, you can just bind one of the implementations to your component. You can achieve this by using a @Component.Builder, or @Binds in a module, or some other way.

    With this approach you would not use a qualifier, as you will only have one Api on your graph that will be used within your component.

    E.g. just bind one instance in your builder.

    @Component
    interface ApiComponent {
      Api api();
    
      @Component.Builder
      interface Builder {
        @BindsInstance Builder api(Api api);
        ApiComponent build();
      }
    }