Reputation: 631
I'm trying some things with Dagger2 but still difficult to understand..
I would like to use 2 services in 2 classes, SplashActivity and HomeActivity. Services depends on NetModule because i would like reuse retrofit and okhttpclient provides.
Here is my NetModule :
@Module
public class NetModule {
@Provides
Retrofit provideRetrofit(@Named("BaseUrl") String baseUrl, OkHttpClient okHttpClient) {
return new Retrofit.Builder()
.baseUrl(baseUrl)
.client(okHttpClient)
.addConverterFactory(GsonConverterFactory.create())
.build();
}
@Provides
HttpLoggingInterceptor provideHttpLoggingInterceptor() {
HttpLoggingInterceptor logging = new HttpLoggingInterceptor();
if (BuildConfig.DEBUG) {
logging.setLevel(HttpLoggingInterceptor.Level.HEADERS);
} else {
logging.setLevel(HttpLoggingInterceptor.Level.NONE);
}
return logging;
}
@Provides
OkHttpClient provideOkHttpClient(HttpLoggingInterceptor httpLoggingInterceptor, @Named("ConnectTimeoutMs") int connectTimeoutMs, @Named("ReadTimeoutMs") int readTimeoutMs) {
return new OkHttpClient.Builder()
.addInterceptor(httpLoggingInterceptor)
.connectTimeout(connectTimeoutMs, TimeUnit.MILLISECONDS)
.readTimeout(readTimeoutMs, TimeUnit.MILLISECONDS)
.build();
}
}
StaticDataModule and StatusModule, it's 2 differents API so they use NetModule :
@Module(includes = NetModule.class)
public class StaticDataModule {
@Provides
@Singleton
StaticDataService provideStaticDataService(Retrofit retrofit) {
return new RetrofitStaticDataService(retrofit);
}
@Provides
@Named("BaseUrl")
String provideBaseUrl() {
return "http://url_static.com";
}
@Provides
@Named("ConnectTimeoutMs")
int provideConnectTimeoutMs() {
return 5000;
}
@Provides
@Named("ReadTimeoutMs")
int provideReadTimeoutMs() {
return 5000;
}
}
@Module(includes = NetModule.class)
public class StatusModule {
@Provides
@Singleton
StatusService provideStatusService(Retrofit retrofit) {
return new RetrofitStatusService(retrofit);
}
@Provides
@Named("BaseUrl")
String provideBaseUrl() {
return "http://url_status.com";
}
@Provides
@Named("ConnectTimeoutMs")
int provideConnectTimeoutMs() {
return 5000;
}
@Provides
@Named("ReadTimeoutMs")
int provideReadTimeoutMs() {
return 5000;
}
}
And i build them in this component :
@Singleton
@Component(modules = {AppModule.class, StaticDataModule.class, StatusModule.class})
public interface AppComponent {
void inject(SplashActivity splashActivity);
void inject(HomeActivity homeActivity);
}
I obtain this error : @javax.inject.Named("BaseUrl") java.lang.String is bound multiple times. I understand my error, dagger dont know who provide between StaticData baseUrl and Status baseUrl.
I tried to make 2 components, StaticDataComponent and StatusComponent, but i can't inject both in the same activity.
I tried to extends NetModule in StaticDataModule and StatusModule, and give parameters with constructor, but multiple bounds error was on retrofit provide.
So i don't know how to reuse NetModule with differents parameters in 2 modules, if someone has an example it should really help me.
Thanks !
Upvotes: 4
Views: 1227
Reputation: 631
Finally i found a simple solution, my architecture was bad. Now i need only one module, and retrofit is not provide, he is build inside StaticData and Status implementation :
@Module
public class NetModule {
@Provides
HttpLoggingInterceptor provideHttpLoggingInterceptor() {
HttpLoggingInterceptor logging = new HttpLoggingInterceptor();
if (BuildConfig.DEBUG) {
logging.setLevel(HttpLoggingInterceptor.Level.HEADERS);
} else {
logging.setLevel(HttpLoggingInterceptor.Level.NONE);
}
return logging;
}
@Provides
OkHttpClient provideOkHttpClient(HttpLoggingInterceptor httpLoggingInterceptor) {
return new OkHttpClient.Builder()
.addInterceptor(httpLoggingInterceptor)
.connectTimeout(5000, TimeUnit.MILLISECONDS)
.readTimeout(5000, TimeUnit.MILLISECONDS)
.build();
}
@Provides
@Singleton
StaticDataService provideStaticDataService(OkHttpClient okHttpClient) {
return new RetrofitStaticDataService("http://url_1.com",okHttpClient);
}
@Provides
@Singleton
StatusService provideStatusService(OkHttpClient okHttpClient) {
return new RetrofitStatusService("http://url_2.com",okHttpClient);
}
}
@Singleton
@Component(modules = {AppModule.class, NetModule.class})
public interface AppComponent {
void inject(SplashActivity splashActivity);
void inject(HomeActivity homeActivity);
}
Retrofit objects are only in retrofit implementation class, so if i need change retrofit by another library i have just to change new RetrofitStaticDataService() by new AnotherStaticDataService().
Thanks for help Anton.
Upvotes: 2
Reputation: 4327
Do not include NetModule.class as dependency to your modules, just include them separately in the component.
@Module(includes = NetModule.class)
public class StaticDataModule {
to
@Module
public class StaticDataModule {
And then use like this:
@Component(modules = {
NetModule.class, StaticDataModule.class
}) public interface FirstComponent {
void inject(WhateverYouWantActivity activity);
}
@Component(modules = {
NetModule.class, StatusModule.class
}) public interface FirstComponent {
void inject(WhateverYouWantSecondActivity activity);
}
If you have to inject into the same activity, you better rework your architecture, but if you still want to do this, you can get rid of inject method, and add something like this:
@Component(modules = { /* your modules */ }) public interface YourComponent {
Retrofit getRetrofit();
OkHttpClient getOkHttpClient();
}
And use it accordingly:
retrofit = yourComponentBuiltByDagger.getRetrofit();
Instead of:
@Inject Retrofit retrofit;
Upvotes: 2