2016-03-09 18 views
13

nềnDagger 2 tiêm nhiều trường hợp của cùng một loại đối tượng

Tôi đang chuyển đổi ứng dụng của tôi để kiến ​​trúc MVP và thấy Dagger 2 để thể hữu ích để tiêm phụ thuộc khi cần thiết. Ứng dụng của tôi cần giao tiếp với hai apis web (api của riêng tôi và api của bên thứ ba). Có thể có những lúc yêu cầu api của riêng tôi và api của bên thứ ba có thể kích hoạt cùng một lúc. Tôi đang sử dụng Retrofit để giao tiếp với các apis này và sử dụng GSON để sắp xếp/deserialisation.

Những gì tôi đã làm trước

Tôi tạo ra hai RestAdapters Retrofit và sử dụng dịch vụ Locator mẫu để có được chúng khi cần thiết. RestAdapter dự định được sử dụng cho api của riêng tôi bao gồm GSONConverter với một số TypeAdapters tùy chỉnh vì tôi không muốn trình tự deserialisation JSON 1: 1 của phản hồi của tôi trong ứng dụng. RestAdapter khác dành cho api của bên thứ ba và sử dụng một GSONConverter khác với chính sách đặt tên trường cụ thể.

Vấn đề

Tôi cố gắng để sử dụng DI thay vì of Service Locator để có được RestAdapter của tôi (và giao diện API). Tôi có thiết lập lớp NetModule của mình như sau

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

Như bạn có thể thấy ở trên trong mã, NetModule có phương thức trả về hai đối tượng Gson và hai đối tượng RestAdapter. Câu hỏi của tôi là;

  1. Làm cách nào để đảm bảo rằng các phụ thuộc chính xác được tiêm khi tạo giao diện API cụ thể của RestAdapter &? (provideMyRestAdapter() đòi hỏi GSON trở về từ provideGsonForMyAPI()provideMyAPI() đòi hỏi RestAdapter trở về từ provideMyRestAdapter().)

  2. Làm thế nào tôi có thể chắc chắn rằng chỉ có hai trường hợp của RestAdapter (Một cho api của tôi và khác cho api của bên thứ ba) đều từng được tạo ra trong suốt cuộc đời của ứng dụng kể từ khi tạo RestAdapter được coi là tốn kém. Tôi đang sử dụng thuộc tính @Named trên các phương thức trả về RestAdapters. Nói ví dụ khi tiêm phụ thuộc trực tiếp vào trường như thế này: @Inject("myApiRestAdapter") RestAdapter myRestadapter; là Dagger 2 sẽ tạo RestAdapter mới mỗi lần hoặc là nó sẽ sử dụng một tạo trước (như @Singleton nhưng đối với đối tượng cụ thể)?

Tôi vừa mới bắt đầu sử dụng Dagger 2 và sự hiểu biết của tôi về cách sử dụng nó có thể vẫn không chính xác. Hãy sửa tôi nếu tôi làm điều gì sai ở đây. Cảm ơn bạn đã chịu đựng câu hỏi dài này.

Trả lời

22

Bạn đã nửa chừng giải pháp. Để hoàn thành các giải pháp cố gắng làm như sau:

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

Để chắc chắn rằng chỉ có hai trường hợp của RestAdapters của bạn được tạo ra trong suốt cuộc đời của ứng dụng, chú thích cả hai phương pháp cung cấp RestAdapter với @Singleton như bạn đã làm với bạn Các phương pháp khác. Đối với câu hỏi khác của bạn cho dù Dagger 2 sẽ tạo ra thể hiện mới của RestAdapter mỗi khi nó đã tiêm nó, tôi nghĩ rằng nó thực hiện điều này chính xác, nhưng tôi không chắc chắn về điều này.

Hy vọng điều này sẽ hữu ích!

+0

Thanks @pratt Tôi sẽ dùng thử.Tôi có một câu hỏi mặc dù, không phải là '@ Singleton' nghĩa vụ phải tạo ra chỉ một đối tượng cho một loại lớp nhất định? Trong trường hợp này Nếu tôi chú thích cả hai adapter còn lại của tôi là '@ Singleton' (thuộc loại RestAdapter) thì điều gì sẽ xảy ra sau hậu trường? –

+1

Ngoài chú thích phương thức của bạn là '@ Singleton', bạn cũng chú thích nó bằng chú thích' @ Named', nó sẽ báo cho dao găm tạo hai cá thể riêng biệt của RestAdapter cho mỗi tên. Hãy chắc chắn tham khảo RestAdapter nào bạn cần bằng cách sử dụng '@ Named' như tôi đã trình bày trong câu trả lời ở trên. – Harry

+0

Điều đó có ý nghĩa, Cảm ơn. Tôi sẽ cố gắng tối nay và trở lại với bạn! –

Các vấn đề liên quan