Ошибка Android Dagger2: @javax.inject.Named("BaseUrl") java.lang.String связывается несколько раз
Я пробую кое-что с Dagger2, но все еще трудно понять..
Я хотел бы использовать 2 сервиса в 2 классах, SplashActivity и HomeActivity. Услуги зависят от NetModule, потому что я хотел бы повторно использовать модификацию и предоставляет okhttpclient.
Вот мой 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 и StatusModule, это 2 разных API, поэтому они используют 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;
}
}
И я строю их в этом компоненте:
@Singleton
@Component(modules = {AppModule.class, StaticDataModule.class, StatusModule.class})
public interface AppComponent {
void inject(SplashActivity splashActivity);
void inject(HomeActivity homeActivity);
}
Я получаю эту ошибку: @javax.inject.Named("BaseUrl") java.lang.String связывается несколько раз. Я понимаю свою ошибку, кинжал не знает, кто обеспечивает между StaticData baseUrl и Status baseUrl.
Я попытался сделать 2 компонента, StaticDataComponent и StatusComponent, но я не могу ввести оба в одной и той же деятельности.
Я пытался расширить NetModule в StaticDataModule и StatusModule, и дать параметры с помощью конструктора, но ошибка множественных границ была при модернизации.
Так что я не знаю, как повторно использовать NetModule с разными параметрами в 2 модулях, если у кого-то есть пример, он действительно должен мне помочь.
Спасибо!
2 ответа
Не включайте NetModule.class как зависимость от ваших модулей, просто включите их отдельно в компонент.
@Module(includes = NetModule.class)
public class StaticDataModule {
в
@Module
public class StaticDataModule {
А затем используйте как это:
@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);
}
Если вам нужно внедрить в то же действие, вам лучше переделать свою архитектуру, но если вы все еще хотите сделать это, вы можете избавиться от метода ввода и добавить что-то вроде этого:
@Component(modules = { /* your modules */ }) public interface YourComponent {
Retrofit getRetrofit();
OkHttpClient getOkHttpClient();
}
И используйте его соответственно:
retrofit = yourComponentBuiltByDagger.getRetrofit();
Вместо:
@Inject Retrofit retrofit;
Наконец я нашел простое решение, моя архитектура была плохой. Теперь мне нужен только один модуль, и модернизация не предусмотрена, он встроен в реализацию StaticData и Status:
@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);
}
Объекты модификации находятся только в классе реализации модернизации, поэтому, если мне нужно изменить модификацию другой библиотеки, мне нужно просто изменить новый RetrofitStaticDataService() на новый AnotherStaticDataService().
Спасибо за помощь, Антон.