Цикл зависимости 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()
    }
}
Другие вопросы по тегам