Android 匕首2注入相同对象类型的多个实例
背景 我正在将我的应用程序转换为MVP架构,发现Dagger 2在需要时注入依赖项非常有用。我的应用程序需要与两个web api(我自己的api和第三方api)通信。有时,对我自己的api和第三方api的请求可能会同时发出。我正在使用改造与这些API通信,并使用GSON进行序列化/反序列化 我以前做过什么 我创建了两个改装重启适配器,并使用服务定位器模式在需要时获取它们。用于我自己的api的RestaAdapter包括带有一些自定义TypeAdapter的GSONConverter,因为我不希望在应用程序中对我的响应进行1:1 JSON反序列化。另一个RestAdapter用于第三方api,并使用另一个具有特定字段命名策略的GSONConverter 问题 我试图使用DI而不是服务定位器来获取我的RestAdapter(和API接口)。我的NetModule类设置如下所示Android 匕首2注入相同对象类型的多个实例,android,retrofit,dagger-2,Android,Retrofit,Dagger 2,背景 我正在将我的应用程序转换为MVP架构,发现Dagger 2在需要时注入依赖项非常有用。我的应用程序需要与两个web api(我自己的api和第三方api)通信。有时,对我自己的api和第三方api的请求可能会同时发出。我正在使用改造与这些API通信,并使用GSON进行序列化/反序列化 我以前做过什么 我创建了两个改装重启适配器,并使用服务定位器模式在需要时获取它们。用于我自己的api的RestaAdapter包括带有一些自定义TypeAdapter的GSONConverter,因为我不希望
@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);
}
}
@模块
公共类网络模块{
私有静态最终字符串MY\u API\u URL=“MY\u API\u URL”;
私有静态最终字符串THIRD\u PARTY\u API\u URL=“THIRD\u PARTY\u API\u URL”;
@提供
@独生子女
缓存provideOkHttpCache(应用程序){
int cacheSize=10*1024*1024;//10 MiB
返回新缓存(application.getCacheDir(),cacheSize);
}
@提供
@独生子女
OkHttpClient提供KHttpClient(缓存){
OkHttpClient=新的OkHttpClient();
setCache(cache);
返回客户;
}
@提供
@独生子女
TypeAdapter提供MyApiTypeAdapter(){
返回新的TypeAdapter(){
//忽略实现
};
}
@提供
@命名为(“myApiGson”)
Gson提供SonFormyapi(类型适配器){
返回新的GsonBuilder()
.registerTypeAdapter(MyClass.class,适配器)
.setDateFormat(“yyyy-MM-dd HH:MM:ss”)
.create();
}
@提供
@命名为(“第三方雅皮格森”)
Gson为第三方提供服务(){
返回新的GsonBuilder()
.setFieldNamingPolicy(FieldNamingPolicy.LOWER_CASE_,带下划线)
.create();
}
@提供
@命名(“Myapirestapter”)
RestAdapter provideMyRestAdapter(Gson Gson、OkHttpClient、OkHttpClient){
返回新的RestAdapter.Builder()
.setEndpoint(MY_API_URL)
.setConverter(新GsonConverter(gson))
.setClient(新的OkClient(okHttpClient))
.build();
}
@提供
@命名(“第三方Pirestadapter”)
RestAdapter提供第三方RestAdapter(Gson Gson、OkHttpClient、OkHttpClient){
返回新的RestAdapter.Builder()
.setEndpoint(第三方API URL)
.setConverter(新GsonConverter(gson))
.setClient(新的OkClient(okHttpClient))
.build();
}
@提供
@独生子女
MyAPI提供MyAPI(重启适配器){
返回adapter.create(MyAPI.class);
}
@提供
@独生子女
第三方适配器提供第三方适配器(重新适配器){
返回adapter.create(ThirdPartyAPI.class);
}
}
正如您在上面的代码中所看到的,NetModule有返回两个Gson对象和两个RestAdapter对象的方法。我的问题是,
provideMyRestAdapter()
需要从provideGsonForMyAPI()
返回的GSON,而provideMyAPI()
需要从provideMyRestAdapter()
返回的RestAdapter)@Named
属性。例如,当将依赖项直接注入如下字段时:@Inject(“myApiRestAdapter”)RestAdapter myRestadapter代码>匕首2是每次都要创建新的重新适应程序,还是要使用以前创建的重新适应程序(如@Singleton
但针对特定对象)
我刚刚开始使用匕首2,我对如何使用它的理解可能仍然不正确。如果我在这里做错了什么,请纠正我。谢谢你接受这个冗长的问题 您已经完成了解决方案的一半。要完成解决方案,请尝试执行以下操作:
@Provides
@Named("myApiRestAdapter")
RestAdapter provideMyRestAdapter(@Named("myApiGson") 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(@Named("thirdPartyApiGson") Gson gson, OkHttpClient okHttpClient) {
return new RestAdapter.Builder()
.setEndpoint(THIRD_PARTY_API_URL)
.setConverter(new GsonConverter(gson))
.setClient(new OkClient(okHttpClient))
.build();
}
要确保在应用程序的生命周期内仅创建两个RestAdapter实例,请像对其他方法一样,为RestAdapter提供@Singleton
注释这两个方法。至于你的另一个问题,Dagger 2是否会在每次注入RestAdapter时创建新的RestAdapter实例,我认为它确实会这样做,但我对此不确定
希望这有帮助 我在发布了我对一个类似问题的回答后看到了这个帖子。我想提供一个链接,因为我认为根据您的情况,同样的方法可能会有用。对于这个确切的问题来说,这可能有些过分,但我想与大家分享一下,以防它对其他人有所帮助
简而言之,您可以为每个命名对象(例如MyApiGson和ThirdPartyApiGson)创建唯一的接口/类,然后为这些对象创建@Provides,而不是通用的Gson类。通过这种方式,您可以按类/接口插入实例,而不是按需要查找或记住的神奇字符串名称。这需要做更多的工作,但如果有一组独立的模块提供同一类的不同实例,则会有所帮助。谢谢@pratt,我会尝试一下。不过我有一个问题,你是不是