#android #dependency-injection #dagger-2 #autofactory
#Android #внедрение зависимостей #dagger-2 #autofactory
Вопрос:
Я использую Dagger-2 (версия 2.7) и AutoFactory (версия 1.0-beta3). Я столкнулся со своеобразной проблемой.
У меня есть класс MyRequest, ctor которого принимает 2 параметра как:
- ConnectivityManager conmgr
- int somevalue
Я создал ctor как
@Autofactory
public MyRequest(@Provider ConnectivityManager conmgr, int somevalue){
//
}
У меня есть модуль, содержащий следующее
@Provides
@SystemScope
public final ConnectivityManager provideConnectivityManager(App app) {
return (ConnectivityManager)
app.getSystemService(Context.CONNECTIVITY_SERVICE);
}
В том же модуле я делаю следующее
@Provides
@SystemScope
public final MyRequestFactory providesMyRequestFactory(ConnectivityManager connectivityManager {
return new MyRequestFactory(connectivityManager);
}
Я получаю ошибку сборки
несовместимых типов: ConnectivityManager не может быть преобразован в Provider < ConnectivityManager> .
Есть идеи, как это решить?
Ответ №1:
Как и в примере с AutoFactory, если ваш конструктор принимает a Foo
, сгенерированный конструктор вашего AutoFactory примет a Provider<Foo>
вместо этого. Это значит, что ваша фабрика будет запрашивать новый Foo
(или ConnectivityManager
) один раз для каждого вызова get
, не обязательно разделяя экземпляры между ними.
Может случиться так, что вы хотите Foo
или ConnectivityManager
должны быть одним и тем же экземпляром для всех экземпляров созданного объекта ( MyRequest
здесь ), но это диктовать вам и Dagger, а не AutoFactory. Следовательно, AutoFactory всегда будет генерировать код, который принимает поставщиков, используете ли вы их таким образом или нет.
К счастью, исправить это очень просто: Dagger может вводить a Provider<ConnectivityManager>
так же легко, как ConnectivityManager
и a (как и для любой привязки), поэтому вы можете просто изменить свой @Provides
метод следующим образом…
@Provides
@SystemScope
public final MyRequestFactory providesMyRequestFactory(
Provider<ConnectivityManager> connectivityManagerProvider {
return new MyRequestFactory(connectivityManagerProvider);
}
… но поскольку ваша сгенерированная фабрика будет иметь @Inject
аннотацию, вам, вероятно, было бы лучше полностью удалить @Provides
метод и позволить Dagger использовать этот конструктор для MyRequestFactory
инъекций. Хотя вы потеряете @SystemScope
аннотацию scope из @Provides
метода, это не проблема: с Provider<ConnectivityManager>
помощью приведенной выше инъекции вам не нужно беспокоиться о жизненном цикле сгенерированной фабрики, поэтому вы можете вернуться к нераскрытому предоставлению по умолчанию.
Комментарии:
1. Спасибо за хорошее объяснение. И по уважительным причинам, почему мне не нужен «@Provides» для «MyRequest». Однако вы могли бы дать представление о том, как Dagger-2 будет вводить Provider<ConnectivityManager>, хотя я предоставляю только ConnectivityManger, используя «@Provides ConnectivityManager» в моем модуле (а не Provider <ConnectivityManager>
2. @shyguy Добро пожаловать! И вам, вероятно, понадобится @Provides для MyRequest, но не для MyRequestFactory. Вы можете ознакомиться с разделом «Привязки на графике» в Руководстве пользователя Dagger 2 для получения подробной информации, но достаточно сказать, что Dagger будет обрабатывать запросы для
Provider<T>
Lazy<T>
, или дажеProvider<Lazy<T>>
для любогоT
, который вы предоставляете с помощью@Provides
метода или иным образом.3. Извините за опечатку, я имел в виду только MyRequestFactory. Я обязательно перейду по предложенной вами ссылке. Еще раз спасибо @Jeff Bowman