Android Dagger2 error: @javax.inject.Named("BaseUrl") java.lang.String is bound multiple times
Android Dagger2 error: @javax.inject.Named("BaseUrl") java.lang.String is bound multiple times
我正在尝试使用 Dagger2 做一些事情,但仍然难以理解..
我想使用 2 个 类 中的 2 个服务,SplashActivity 和 HomeActivity。
服务依赖于 NetModule 因为我想重用改造和 okhttpclient 提供。
这是我的网络模块:
@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 被多次绑定。
我理解我的错误,dagger 不知道谁在 StaticData baseUrl 和 Status baseUrl 之间提供。
我尝试制作 2 个组件,StaticDataComponent 和 StatusComponent,但我无法将两者注入同一个 activity。
我尝试在 StaticDataModule 和 StatusModule 中扩展 NetModule,并使用构造函数提供参数,但改造提供时出现多边界错误。
所以我不知道如何在 2 个模块中重用具有不同参数的 NetModule,如果有人有示例,它应该真的对我有帮助。
谢谢!
不要将 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);
}
如果你必须注入相同的 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);
}
翻新对象仅在翻新实现中 class,因此如果我需要通过另一个库更改翻新,我只需将新的 RetrofitStaticDataService() 更改为新的 AnotherStaticDataService()。
感谢安东的帮助。
我正在尝试使用 Dagger2 做一些事情,但仍然难以理解..
我想使用 2 个 类 中的 2 个服务,SplashActivity 和 HomeActivity。 服务依赖于 NetModule 因为我想重用改造和 okhttpclient 提供。
这是我的网络模块:
@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 被多次绑定。 我理解我的错误,dagger 不知道谁在 StaticData baseUrl 和 Status baseUrl 之间提供。
我尝试制作 2 个组件,StaticDataComponent 和 StatusComponent,但我无法将两者注入同一个 activity。
我尝试在 StaticDataModule 和 StatusModule 中扩展 NetModule,并使用构造函数提供参数,但改造提供时出现多边界错误。
所以我不知道如何在 2 个模块中重用具有不同参数的 NetModule,如果有人有示例,它应该真的对我有帮助。
谢谢!
不要将 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);
}
如果你必须注入相同的 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);
}
翻新对象仅在翻新实现中 class,因此如果我需要通过另一个库更改翻新,我只需将新的 RetrofitStaticDataService() 更改为新的 AnotherStaticDataService()。
感谢安东的帮助。