Dagger 2 inyecta múltiples instancias del mismo tipo de objeto

Fondo

Estoy convirtiendo mi aplicación a MVP arquitectura y encontré Dagger 2 para ser útil para inyectar dependencias cuando sea necesario. Mi aplicación debe comunicarse con dos apis web (mi propia y una api de terceros). Puede haber ocasiones en las que las solicitudes a mi propio api y el api de terceros podrían disparar al mismo tiempo. Estoy utilizando Retrofit para comunicarse con estos apis y usar GSON para serialistation / deserialisation.

Lo que hice antes

Creé dos Retrofit RestAdapters y utilicé el patrón de Service Locator para obtenerlos cuando sea necesario. El RestAdapter destinado a ser utilizado para mi propia api incluye GSONConverter con algunos Custom TypeAdapters ya que no quiero deserialización JSON 1: 1 de mi respuesta en la aplicación. El otro RestAdapter fue diseñado para api de terceros y utiliza otro GSONConverter con una política de nomenclatura de campos específica.

Problema

Estoy tratando de usar DI en lugar de Service Locator para obtener mi RestAdapter (y la interfaz API). Tengo mi configuración de clase NetModule como sigue

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

Como se puede ver arriba en el código, el NetModule tiene métodos para devolver dos objetos Gson y dos objetos RestAdapter. Mis preguntas son;

  1. ¿Cómo me aseguro de que se inyecten las dependencias correctas al crear Interfaces RestAdapter y API específicos? ( provideMyRestAdapter() requiere GSON devuelto de provideGsonForMyAPI() y provideMyAPI() requiere RestAdapter devuelto from provideMyRestAdapter() .)

  2. ¿Cómo puedo asegurarme de que solo se hayan creado dos instancias de RestAdapter (One for my api y otras para api de terceros) durante la vida útil de la aplicación, ya que la creación de RestAdapter se considera costosa. Estoy utilizando el atributo @Named en los métodos que devuelven RestAdapters. Digamos, por ejemplo, cuando se inyecta la dependencia directamente al campo como este: @Inject("myApiRestAdapter") RestAdapter myRestadapter; Dagger 2 va a crear nuevo RestAdapter cada vez o va a utilizar uno creado antes (como @Singleton pero para el objeto específico)?

Acabo de empezar a usar Dagger 2 y mi comprensión de cómo usarlo todavía puede ser incorrecta. Por favor, corrija si estoy haciendo algo mal aquí. Gracias por soportar esta larga pregunta.

Ya está a la mitad de la solución. Para completar la solución, intente hacer lo siguiente:

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

Para asegurarse de que sólo se crean dos instancias de sus RestAdapters durante la vida útil de la aplicación, anote ambos métodos que proporcionan RestAdapter con @Singleton como lo han hecho con otros métodos. En cuanto a su otra pregunta si Dagger 2 va a crear una nueva instancia de RestAdapter cada vez que tiene que inyectar, creo que hace esto exactamente, pero no estoy seguro de esto.

¡Espero que esto ayude!

FlipAndroid es un fan de Google para Android, Todo sobre Android Phones, Android Wear, Android Dev y Aplicaciones para Android Aplicaciones.