Ero piuttosto pigro e usavo quasi tutte le iniezioni sul campo. Stavo solo fornendo un costruttore vuoto, inserisco i miei campi @Inject, tutto sembrava bello e semplice. Comunque l'iniezione sul campo ha i suoi compromessi, quindi ho escogitato alcune semplici regole che mi aiutano a decidere quando usare il campo e quando usare le iniezioni del costruttore. Apprezzerò qualsiasi feedback se c'è un errore nella mia logica o se hai ulteriori considerazioni da aggiungere.Daga 2: quando utilizzare le iniezioni del costruttore e quando utilizzare le iniezioni sul campo?
Prima qualche chiarimento al fine di essere sulla stessa pagina:
iniezione Costruttore:
@Inject
public SomeClass(@Named("app version") String appVersion,
AppPrefs appPrefs) {...
Lo stesso con il campo di iniezione:
public class SomeClass {
@Inject
@Named("app version") String mAppVersion;
@Inject
AppPrefs appPrefs;
Regola 1: deve utilizzare campo iniezione se non controllo la creazione dell'oggetto (pensa Attività o Frammento in Android). Se alcuni framework (non a prova di Dagger) creano il mio oggetto e me lo gestiscono non ho altra scelta che iniettarlo manualmente dopo aver ricevuto l'istanza.
Regola 2: DEVE utilizzare l'iniezione del costruttore se la classe è/può essere utilizzata in un altro progetto che non utilizza Dagger 2. Se gli altri progetti non usano Dagger, non possono usare DI, quindi l'utente deve creare l'oggetto "vecchio" utilizzando new
.
Regola 3: Iniezione PREFER del costruttore quando si lavora con le gerarchie di classi perché è più semplice creare test di unità.
Chiarificazione:
Considerando la seguente struttura che utilizza l'iniezione campo:
package superclass;
public class SuperClass {
@Inject
HttpClient mHttpClient;
...
}
.
package differentpackage;
public class SubClass extends SuperClass {
public SubClass() {
}
}
Quando sto creando unit test per SubClass
nella directory test/java/differentpackage
non ho altra scelta, ma per far apparire l'intera infrastruttura DI al fine di essere in grado di iniettare il HttpClient
. Al contrario, se stavo usando l'iniezione del costruttore in questo modo:
public class SuperClass {
private final HttpClient mHttpClient;
@Inject
public SuperClass(HttpClient httpClient) {
mHttpClient = httpClient;
}
}
nel mio test di unità che potevo semplicemente:
HttpClient mockHttp = mock(HttpClient.class);
Subclass tested = new Subclass(mockHttp);
// tests
Quindi, in pratica ora sono in un altro estremo: tendo a fare affidamento soprattutto su Iniezioni del costruttore e utilizzare le iniezioni sul campo solo quando si applica la "Regola 1". L'unico 'problema' che ho con il costruttore inietta è che per le classi di 'fine' costruttori a volte diventano abbastanza sovraccaricati con i parametri e guardano prolisso e brutto come questo:
@Inject
public ModelMainImpl(@Named("app version") String appVersion,
AppPrefs appPrefs,
LoginPrefs loginPrefs,
@ForApplication Context appContext,
NetworkInfoProvider networkInfoProvider,
AndroidEventPoster androidEventPoster,
Session session,
ForgeExchangeManager exchangeManager,
HttpFunctionality httpFunctionality,
@Named("base url") String baseUrl,
@Named("forge result producer") ResultProducer<ForgeExchangeResult> resultProducer
) {
Ragazzi, quali sono le regole per scegliere tra costruttore e campo inietti? Mi manca qualcosa, ci sono errori nella mia logica?
https://stackoverflow.com/questions/39207845/android-dagger-2-inject-versus-provides Guarda anche questo, offre una buona visione –