Mehdi Mousavi
Mehdi Mousavi

Reputation: 125

Provide two different instances of the same type

I have a Dagger module with two @Provides methods that construct different Retrofit instances. I also have two methods that each need to consume one of the Retrofit instances.

How do I tell Dagger which Retrofit I want to use in each of the consuming functions?

My code :

@Provides
@Singleton
public OkHttpClient provideOkHttpClient(){
    final OkHttpClient.Builder builder = new OkHttpClient.Builder();

    if (BuildConfig.DEBUG) {
        HttpLoggingInterceptor logging = new HttpLoggingInterceptor();
        logging.setLevel(HttpLoggingInterceptor.Level.BODY);
        builder.addInterceptor(logging);
    }

    builder.connectTimeout(60 * 1000, TimeUnit.MILLISECONDS)
            .readTimeout(60 * 1000, TimeUnit.MILLISECONDS);

    return builder.build();
}

@Provides
@Singleton
public Retrofit provideRestAdapter1(Application application, OkHttpClient okHttpClient) {
    Retrofit.Builder builder = new Retrofit.Builder();
    builder.client(okHttpClient)
            .baseUrl(application.getString(R.string.Endpoint1))
            .addCallAdapterFactory(RxJava2CallAdapterFactory.create())
            .addConverterFactory(GsonConverterFactory.create());
    return builder.build();
}

@Provides
@Singleton
public Retrofit provideRestAdapter2(Application application, OkHttpClient okHttpClient) {
    Retrofit.Builder builder = new Retrofit.Builder();
    builder.client(okHttpClient)
            .baseUrl(application.getString(R.string.Endpoint2))
            .addCallAdapterFactory(RxJava2CallAdapterFactory.create())
            .addConverterFactory(GsonConverterFactory.create());
    return builder.build();
}

@Provides
@Singleton
public GithubApiService provideGithubApiService(Retrofit restAdapter) {
    return restAdapter.create(GithubApiService.class);
}

@Provides
@Singleton
public GithubApiService2 provideGithubApiService(Retrofit restAdapter) {
    return restAdapter.create(GithubApiService2.class);
}

}

Upvotes: 1

Views: 113

Answers (2)

Samuel Peter
Samuel Peter

Reputation: 4166

You can use @Qualifier annotations to distinguish between the two.

First create a new annotation type (in its own java file of course):

@Qualifier
@Retention(RetentionPolicy.RUNTIME)
public @interface EndPoint1 {

}

Then annotate the relevant @Provides method:

@Provides
@Singleton
@EndPoint1
public Retrofit provideRestAdapter1(Application application, OkHttpClient okHttpClient) {
    ...
}

And then tell Retrofit to use this one in the other @Provides:

@Provides
@Singleton
public GithubApiService provideGithubApiService(@EndPoint1 Retrofit restAdapter) {
    return restAdapter.create(GithubApiService.class);
}

You can also use @Named if you don't want to create you own annotations. See the documentation here.

Upvotes: 2

Himeshgiri gosvami
Himeshgiri gosvami

Reputation: 2884

You can also use name parameter

use this code

@Provides
@Singleton
@Named("Google")
Retrofit providePlaceApiClient(OkHttpClient client, Gson gson) {
    return new Retrofit.Builder()
            .baseUrl(BaseApiConfig.getPlaceApiUrl())
            .client(client)
            .addConverterFactory(GsonConverterFactory.create(gson))
            .addCallAdapterFactory(RxJavaCallAdapterFactory.create())
            .build();
}

@Provides
@Singleton
Retrofit provideRetrofit(OkHttpClient client, Gson gson) {
    return new Retrofit.Builder()
            .baseUrl(BaseApiConfig.getBaseUrl())
            .client(client)
            .addConverterFactory(GsonConverterFactory.create(gson))
            .addCallAdapterFactory(RxJavaCallAdapterFactory.create())
            .build();
}

You can get this using named annotation with inject annotation.

@Inject
@Named("Google")
Retrofit retrofit

Also, you can add on your component for child referance

@Named("Google")
Retrofit providePlaceApiClient();

Upvotes: 1

Related Questions