Я был вроде ленив и использовал почти полностью полевые инъекции. Я просто предоставлял пустой конструктор, поместил поля @Inject, все выглядело красиво и просто. Однако у полевых инъекций есть свои компромиссы, поэтому я разработал несколько простых правил, которые помогают мне решить, когда использовать поле и когда использовать инъекции конструктора. Я буду признателен за любые отзывы, если в моей логике есть ошибка или у вас есть дополнительные соображения для добавления.Кинжал 2: Когда использовать инъекции конструктора и когда использовать полевые инъекции?
Сначала некоторые разъяснения для того, чтобы быть на той же странице:
инъекции Constructor:
@Inject
public SomeClass(@Named("app version") String appVersion,
AppPrefs appPrefs) {...
То же самое с инъекцией поля:
public class SomeClass {
@Inject
@Named("app version") String mAppVersion;
@Inject
AppPrefs appPrefs;
Правило 1: ДОЛЖЕН использовать поле если я не контролирую создание объекта (подумайте об активности или фрагменте в Android). Если какая-то (не-кинжалная) структура создает мой объект и обрабатывает его для меня, у меня нет выбора, кроме как ввести его вручную после получения экземпляра.
Правило 2: ДОЛЖНО использовать инъекцию конструктора, если класс используется/может использоваться в другом проекте, который не использует кинжал 2. Если другие проекты не используют кинжал, они не могут использовать DI, поэтому пользователю необходимо создать объект «старый» способ, используя new
.
Правило 3: Встраивание конструктора PREFER при работе с иерархиями классов, поскольку легче создавать модульные тесты.
Пояснение:
Учитывая следующую структуру, которая использует инъекции поля:
package superclass;
public class SuperClass {
@Inject
HttpClient mHttpClient;
...
}
.
package differentpackage;
public class SubClass extends SuperClass {
public SubClass() {
}
}
Когда я создаю модульное тестирование для SubClass
в каталоге test/java/differentpackage
У меня нет выбора, кроме как поднять всю инфраструктуру DI для того, чтобы иметь возможность впрыскивать HttpClient
. В отличие от этого, если бы я использовал инъекции конструктора, как это:
public class SuperClass {
private final HttpClient mHttpClient;
@Inject
public SuperClass(HttpClient httpClient) {
mHttpClient = httpClient;
}
}
в моей модульного теста я мог бы просто:
HttpClient mockHttp = mock(HttpClient.class);
Subclass tested = new Subclass(mockHttp);
// tests
Так в основном сейчас я нахожусь в другой крайности: я, как правило, полагаются в основном на инъекции конструктора и использовать полевые инъекции только тогда, когда применяется «Правило 1». Единственная «проблема», что у меня есть с конструктором впрыскивает является то, что для классов «конец» Конструкторы иногда становятся весьма перегружены с параметрами, и они выглядят многословным и уродливые, как это:
@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
) {
Ребята, каковы ваши правила в выбирать между конструктором и полевыми инъекциями? Я что-то упускаю, есть ошибки в моей логике?
https://stackoverflow.com/questions/39207845/android-dagger-2-inject-versus-provides Посмотрите на это, также хорошо понимая –