Background
I am converting my app to MVP architecture and found Dagger 2 to be useful to inject dependencies when needed. My app needs to communicate with two web apis (my own and a third party api). There may be times where requests to my own api and the third party api could fire at the same time. I am using Retrofit to communicate with these apis and using GSON for serialistation / deserialisation.
What I did before
I created two Retrofit RestAdapters and used Service Locator pattern to obtain them when needed. The RestAdapter intended to be used for my own api includes GSONConverter with some custom TypeAdapters since I do not want 1:1 JSON deserialisation of my response in the app. The other RestAdapter intended for third party api and uses another GSONConverter with a specific field naming policy.
Problem
I am trying to use DI instead of Service Locator to obtain my RestAdapter (and the API interface). I have my NetModule class setup like follows
@Module
public class NetModule {
private static final String MY_API_URL = "my_api_url";
private static final String THIRD_PARTY_API_URL = "third_party_api_url";
@Provides
@Singleton
Cache provideOkHttpCache(Application application) {
int cacheSize = 10 * 1024 * 1024; // 10 MiB
return new Cache(application.getCacheDir(), cacheSize);
}
@Provides
@Singleton
OkHttpClient provideOkHttpClient(Cache cache) {
OkHttpClient client = new OkHttpClient();
client.setCache(cache);
return client;
}
@Provides
@Singleton
TypeAdapter<MyClass> provideMyAPITypeAdapter() {
return new TypeAdapter<MyClass>() {
// implementation ignored
};
}
@Provides
@Named("myApiGson")
Gson provideGsonForMyAPI(TypeAdapter<MyClass> adapter) {
return new GsonBuilder()
.registerTypeAdapter(MyClass.class, adapter)
.setDateFormat("yyyy-MM-dd HH:mm:ss")
.create();
}
@Provides
@Named("thirdPartyApiGson")
Gson provideGsonForThirdPartyAPI() {
return new GsonBuilder()
.setFieldNamingPolicy(FieldNamingPolicy.LOWER_CASE_WITH_UNDERSCORES)
.create();
}
@Provides
@Named("myApiRestAdapter")
RestAdapter provideMyRestAdapter(Gson gson, OkHttpClient okHttpClient) {
return new RestAdapter.Builder()
.setEndpoint(MY_API_URL)
.setConverter(new GsonConverter(gson))
.setClient(new OkClient(okHttpClient))
.build();
}
@Provides
@Named("thirdPartyApiRestAdapter")
RestAdapter provideThirdPartyRestAdapter(Gson gson, OkHttpClient okHttpClient) {
return new RestAdapter.Builder()
.setEndpoint(THIRD_PARTY_API_URL)
.setConverter(new GsonConverter(gson))
.setClient(new OkClient(okHttpClient))
.build();
}
@Provides
@Singleton
MyAPI provideMyAPI(RestAdapter adapter){
return adapter.create(MyAPI.class);
}
@Provides
@Singleton
ThirdPartyAPI provideThirdPartyAPI(RestAdapter adapter){
return adapter.create(ThirdPartyAPI.class);
}
}
As you can see above in the code, the NetModule has methods to return two Gson objects and two RestAdapter objects. My questions are;
How do I make sure that the correct dependencies are injected when creating specific RestAdapter & API Interfaces? (
provideMyRestAdapter()
requires GSON returned fromprovideGsonForMyAPI()
andprovideMyAPI()
requires RestAdapter returned fromprovideMyRestAdapter()
.)How can I make sure that only two instances of RestAdapter (One for my api and other for third party api) are ever created during the lifetime of the application since creating RestAdapter is considered to be expensive. I am using
@Named
attribute on methods returning RestAdapters. Say for example when injecting dependency directly to field like this:@Inject("myApiRestAdapter") RestAdapter myRestadapter;
is Dagger 2 going to create new RestAdapter every time or is it going to use one created before (like@Singleton
but for specific object)?
I have just started using Dagger 2 and my understanding of how to use it may still be incorrect. Please correct me if I am doing something wrong here. Thanks for bearing up with this long question.