Warning: file_get_contents(/data/phpspider/zhask/data//catemap/3/android/229.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/0/search/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Android 匕首2注入相同对象类型的多个实例_Android_Retrofit_Dagger 2 - Fatal编程技术网

Android 匕首2注入相同对象类型的多个实例

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,因为我不希望

背景

我正在将我的应用程序转换为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类设置如下所示

@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对象的方法。我的问题是,

  • 如何确保在创建特定的RestAdapter&API接口时注入正确的依赖项?(
    provideMyRestAdapter()
    需要从
    provideGsonForMyAPI()
    返回的GSON,而
    provideMyAPI()
    需要从
    provideMyRestAdapter()
    返回的RestAdapter)

  • 我如何确保在应用程序的生命周期内只创建两个RestAdapter实例(一个用于我的api,另一个用于第三方api),因为创建RestAdapter被认为是昂贵的。我正在对返回restardapters的方法使用
    @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,我会尝试一下。不过我有一个问题,你是不是