SfondoDagger 2 iniettando più istanze dello stesso tipo di oggetto
sto convertendo la mia app all'architettura MVP e ho trovato Dagger 2 per essere utile per iniettare le dipendenze quando necessario. La mia app ha bisogno di comunicare con due web apis (la mia e una terza parte). Potrebbero esserci delle volte in cui le richieste alla mia API e alla API di terze parti potrebbero essere attivate contemporaneamente. Uso Retrofit per comunicare con queste apis e utilizzare GSON per la serializzazione/deserializzazione.
Quello che ho fatto prima
ho creato due RestAdapters Retrofit e usato modello Service Locator per ottenerli quando necessario. Il RestAdapter pensato per essere utilizzato per la mia API personale include GSONConverter con alcuni TypeAdapter personalizzati poiché non desidero la deserializzazione JSON 1: 1 della mia risposta nell'app. L'altro RestAdapter è destinato all'API di terze parti e utilizza un altro GSONConverter con una specifica politica di denominazione dei campi.
Problema
Sto cercando di usare al posto di DI Service Locator per ottenere la mia RestAdapter (e l'interfaccia API). Io ho la mia impostazione di classe NetModule come segue
@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);
}
}
Come si può vedere sopra nel codice, il NetModule ha metodi per restituire due oggetti GSON e due oggetti RestAdapter. Le mie domande sono;
Come posso fare in modo che le dipendenze corrette vengono iniettati durante la creazione di specifici RestAdapter & interfacce API? (
provideMyRestAdapter()
richiede GSON tornato daprovideGsonForMyAPI()
eprovideMyAPI()
richiede RestAdapter tornato daprovideMyRestAdapter()
.)Come posso fare in modo che solo due casi di RestAdapter (uno per il mio api e altri per l'API di terze parti) vengono mai creato durante la vita dell'applicazione poiché la creazione di RestAdapter è considerata costosa. Sto usando l'attributo
@Named
sui metodi che restituiscono RestAdapters. Ad esempio, quando si inserisce direttamente una dipendenza in un campo come questo:@Inject("myApiRestAdapter") RestAdapter myRestadapter;
Dagger 2 creerà ogni volta un nuovo RestAdapter o ne utilizzerà uno creato prima (come@Singleton
ma per un oggetto specifico)?
Ho appena iniziato a utilizzare Dagger 2 e la mia comprensione di come utilizzarlo potrebbe essere ancora errata. Per favore correggimi se sto facendo qualcosa di sbagliato qui. Grazie per aver risposto a questa lunga domanda.
Grazie a @pratt ci proverò.Ho una domanda, però, non '@ Singleton' dovrebbe creare un solo oggetto per un dato tipo di classe? In questo caso, se annoto entrambi i miei adattatori di riposo come '@ Singleton' (che è di tipo RestAdapter) cosa succederà dietro le quinte? –
Oltre ad annotare il tuo metodo come '@ Singleton', lo stai annotando anche con l'annotazione' @ Named' che dirà a dagger di creare due distinte istanze di RestAdapter per ciascun nome. Assicurati di fare riferimento a quale RestAdapter ti serve usando '@ Named 'come mostrato nella risposta sopra. – Harry
Questo ha senso, grazie. Ci proverò stasera e tornerò da te! –