2016-03-09 42 views
13

背景匕首2注入相同的對象類型

我我的應用程序轉換爲MVP架構,發現匕首2在需要時是有用的注入依賴的多個實例。我的應用需要與兩個網絡apis(我自己和第三方api)進行通信。有些時候,我自己的api和第三方api的請求可能會同時觸發。我正在使用Retrofit與這些apis進行通信,並使用GSON進行序列化/反序列化。

我做什麼之前

我創建了兩個改造RestAdapters和使用Service Locator模式在需要時獲得他們。旨在用於我自己的api的RestAdapter包括帶有一些自定義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); 
    } 
} 

正如你可以在代碼中看到上述情況,NetModule有方法返回兩個GSON對象和兩個RestAdapter對象。我的問題是;

  1. 我如何確保創建特定RestAdapter & API接口時,正確的依賴注入? (provideMyRestAdapter()需要GSON從provideGsonForMyAPI()回來,provideMyAPI()需要RestAdapter從provideMyRestAdapter()返回。)

  2. 我怎樣才能確保(一個用於我的API和其他第三方API)RestAdapter的只有兩個實例的生命週期過程中所創造因爲創建RestAdapter的應用程序被認爲是昂貴的。我在返回RestAdapters的方法上使用@Named屬性。比如說,當像這樣直接向字段注入依賴關係時:@Inject("myApiRestAdapter") RestAdapter myRestadapter;是Dagger 2每次都要創建新的RestAdapter,還是要使用之前創建的(比如@Singleton,但是用於特定對象)?

我剛開始用匕首2和我的如何使用它理解可能仍然是不正確的。如果我在這裏做錯了,請糾正我。感謝您支持這個長期的問題。

回答

22

您已經完成了解決方案的一半。爲完善解決方案儘量做到以下幾點:

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

爲了確保只有兩個你RestAdapters實例的應用程序生命週期過程中創建,註釋都提供RestAdapter與@Singleton的方法,如你有做你的其他方法。至於你的其他問題,Dagger 2是否會在每次注入時都創建RestAdapter的新實例,我認爲它完全是這樣做的,但我不確定這一點。

希望這會有所幫助!

+0

謝謝@pratt我會試試看。我有一個問題,是不是'@ Singleton'應該只爲給定的類類型創建一個對象?在這種情況下,如果我將其餘的適配器註釋爲@ @ Singleton(RestAdapter類型),幕後會發生什麼? –

+1

除了將您的方法註釋爲'@ Singleton',您還可以使用'@ Named'註釋對其進行註釋,該註釋將告訴匕首爲每個名稱創建RestAdapter的兩個不同實例。請確保通過使用'@ Named'來引用您需要的RestAdapter,就像我在上面的答案中所顯示的那樣。 – Harry

+0

這很有道理,謝謝。我今晚會嘗試這個,回到你身邊! –