Dagger 2注入相同对象类型的多个实例 [英] Dagger 2 injecting multiple instances of same object type

查看:190
本文介绍了Dagger 2注入相同对象类型的多个实例的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

背景

我正在将我的应用转换为MVP架构,并发现Dagger 2在需要时可用于注入依赖项。我的应用程序需要与两个Web API(我自己的API和第三方API)进行通信。有时候,对我自己的api和第三方api的请求可能会同时触发。我正在使用Retrofit与这些api通信,并使用GSON进行序列化/反序列化。

I am converting my app to MVP architecture and found Dagger 2 to be useful to inject dependencies when needed. My app needs to communicate with two web apis (my own and a third party api). There may be times where requests to my own api and the third party api could fire at the same time. I am using Retrofit to communicate with these apis and using GSON for serialistation / deserialisation.

我以前做过的事情

我创建了两个Retrofit RestAdapters,并使用Service Locator模式在需要时获取它们。打算用于我自己的api的RestAdapter包括带有一些自定义TypeAdapter的GSONConverter,因为我不想在应用程序中对我的响应进行1:1 JSON反序列化。另一个RestAdapter适用于第三方api,并使用具有特定字段命名策略的另一个GSONConverter。

I created two Retrofit RestAdapters and used Service Locator pattern to obtain them when needed. The RestAdapter intended to be used for my own api includes GSONConverter with some custom TypeAdapters since I do not want 1:1 JSON deserialisation of my response in the app. The other RestAdapter intended for third party api and uses another GSONConverter with a specific field naming policy.

问题

我正在尝试使用DI而不是Service Locator来获取我的RestAdapter(和API接口)。我有如下所示的NetModule类设置

I am trying to use DI instead of Service Locator to obtain my RestAdapter (and the API interface). I have my NetModule class setup like follows

@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);
    }
}

如上面的代码所示,NetModule具有返回两个Gson对象和两个RestAdapter对象的方法。我的问题是;

As you can see above in the code, the NetModule has methods to return two Gson objects and two RestAdapter objects. My questions are;


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

  1. How do I make sure that the correct dependencies are injected when creating specific RestAdapter & API Interfaces? (provideMyRestAdapter() requires GSON returned from provideGsonForMyAPI() and provideMyAPI() requires RestAdapter returned from provideMyRestAdapter().)

如何确保在应用程序的生存期内,仅创建过两个RestAdapter实例(一个用于我的api,另一个用于第三方api),因为创建RestAdapter被认为是昂贵的。我在返回RestAdapters的方法上使用 @Named 属性。例如,当直接将依赖项注入字段时,例如: @Inject( myApiRestAdapter)RestAdapter myRestadapter; 是Dagger 2每次创建新的RestAdapter还是将使用以前创建的对象(例如 @Singleton 但用于特定对象)?

How can I make sure that only two instances of RestAdapter (One for my api and other for third party api) are ever created during the lifetime of the application since creating RestAdapter is considered to be expensive. I am using @Named attribute on methods returning RestAdapters. Say for example when injecting dependency directly to field like this: @Inject("myApiRestAdapter") RestAdapter myRestadapter; is Dagger 2 going to create new RestAdapter every time or is it going to use one created before (like @Singleton but for specific object)?

我刚开始使用Dagger 2,但对如何使用Dagger 2的理解仍然不正确。如果我在这里做错了,请纠正我。感谢您解决这个长期的问题。

I have just started using Dagger 2 and my understanding of how to use it may still be incorrect. Please correct me if I am doing something wrong here. Thanks for bearing up with this long question.

推荐答案

您已经解决了一半。要完成该解决方案,请尝试执行以下操作:

You are already halfway through the solution. To complete the solution try to do the following:

@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的新实例,我认为它确实做到了这一点,但是我不确定。

To make sure that only two instances of your RestAdapters are created during the lifetime of the application, annotate both the methods providing RestAdapter with @Singleton like you have done with your other methods. As for your other question whether Dagger 2 will create new instance of RestAdapter every time it has to inject it, I think it does this exactly, but I'm not sure on this.

希望这会有所帮助!

这篇关于Dagger 2注入相同对象类型的多个实例的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆