Цикл зависимости Android-кинжалов
У меня есть 2 зависимости с той же областью, которые требуют друг от друга.
Мои зависимости - это доменные сервисы с разными методами (у каждого метода свой бизнес-кейс). некоторые бизнес-кейсы могут использовать методы из другого домена.
Для этого мне нужно, чтобы домен1 был доступен для домена2 и наоборот.
но когда я делаю это, я получаю ошибку компиляции цикла зависимости. после некоторого времени поиска в Google я обнаружил, что для преодоления этой проблемы я должен внедрить одну из зависимостей с аннотацией @Inject вместо параметра конструктора в модуле @Module.
когда я пытаюсь это сделать, код компилируется, но кинжал вообще не вводит вторую зависимость.
Есть ли способ достичь того, что я хочу с Dagger?
2 ответа
Ваша проблема: AClass имеет зависимость конструктора от BClass, которая имеет зависимость конструктора от AClass. Даже без Dagger это не сработало бы: если бы они зависели друг от друга, что бы вы создали в первую очередь?
Ваше решение: Если вы создаете один из ваших классов (BClass), используя new
и больше не имеет @Inject
-аннотированный конструктор, вы можете подождать, пока не будет создан AClass, чтобы заполнить ваш экземпляр BClass. Однако, если вы создаете объект, используя new
, вам нужно будет ввести его, передав его в метод членов-инъекций или MembersInjector<BClass>
объект. Вам также необходимо убедиться, что это происходит за пределами @Provides
метод (потому что вся причина @Provides
вызывается, так что вы можете создать значение для передачи в конструктор AClass). Это хрупкое и довольно безобразное.
Мое предложение: использовать косвенное обращение через провайдера. Имейте AClass, чтобы ввести Provider<BClass>
или BClass inject Provider<AClass>
, или оба. Пока ты не звонишь get
внутри конструктора вы позволите Dagger создавать AClass и откладывать создание BClass до тех пор, пока он вам не понадобится. Вам не нужно никаких дополнительных настроек, чтобы ввести Provider<T>
или же Lazy<T>
для любого класса T, который вы связали в своем Компоненте; см. "Привязки на графике" в Руководстве пользователя для получения полного списка доступных инъекций.
Я сделал это возможным с помощью dagger.Lazy и Hilt (почти так же, как dagger - он использует кинжал под капотом). Но будь осторожен. Круговая зависимость может быть результатом плохого дизайна и может привести ко многим проблемам. Вот пример:
class Cls1 @Inject constructor() {
@Inject lateinit var cls2: dagger.Lazy<Cls2>
}
class Cls2 @Inject constructor() {
@Inject lateinit var cls1: dagger.Lazy<Cls1>
}
@HiltAndroidApp
class ApplicationClass: Application() {
@Inject lateinit var cls1: Cls1
@Inject lateinit var cls2: Cls2
override fun onCreate() {
super.onCreate()
}
}