Сколько Dagger компонентов может быть в приложении

Ответ

Количество Dagger компонентов в приложении не ограничено и зависит от архитектуры. Обычно используют:

  1. Один компонент – для простых приложений (не рекомендуется для больших проектов).
  2. Множество компонентов – для модульности, разделения зависимостей (например, AppComponent, AuthComponent, FeatureComponent).

Пример иерархии:

@Singleton
@Component(modules = [AppModule::class])
interface AppComponent {
    fun authComponent(): AuthComponent.Factory
}

@Component(dependencies = [AppComponent::class])
interface AuthComponent {
    @Component.Factory
    interface Factory {
        fun create(appComponent: AppComponent): AuthComponent
    }
}

Лучшие практики:

  • Разделять компоненты по функциональности/модулям.
  • Использовать сабкомпоненты или зависимости для связи.
  • Избегать гигантских компонентов.

Ответ 18+ 🔞

Э, слушай, а вот насчёт этих Dagger компонентов — тут вообще-то полная свобода, как в анекдоте про блондинку и унитаз. Хочешь — один сделай, хочешь — овердохуища. Но если серьёзно, то всё упирается в то, насколько у тебя приложение не в дугу, понимаешь?

Вот смотри. Если у тебя приложение — как та мартышлюшка, которая только и умеет, что кнопку нажимать и «Hello World» показывать, то можешь хоть одним компонентом обойтись. Создал один @Singleton компонент, запихнул туда все модули разом — и вроде как работает. Но это, ёпта, путь в ад. Потому что потом, когда проект вырастет, этот единственный компонент превратится в такого монстра, что разобраться в нём будет сложнее, чем найти иголку в стоге сена, который ещё и горит. Доверия к такому решению — ноль ебать.

Нормальные пацаны делают так: дробишь всё по смыслу. Вот смотри на пример, он как раз про это:

@Singleton
@Component(modules = [AppModule::class])
interface AppComponent {
    // Ключевой момент! Даём фабрику для создания дочернего компонента
    fun authComponent(): AuthComponent.Factory
}

// Другой компонент, который зависит от основного
@Component(dependencies = [AppComponent::class])
interface AuthComponent {
    @Component.Factory
    interface Factory {
        fun create(appComponent: AppComponent): AuthComponent
    }
}

Видишь маневр? У нас есть главный AppComponent — это как бы склад общих штук (сеть, база данных, shared preferences, ну ты понял). А потом, когда нам нужно зайти в модуль авторизации, мы не начинаем тащить в него всё подряд из главного компонента. Нет! Мы говорим: «Слушай, AuthComponent, вот тебе доступ к общему складу (AppComponent). Бери оттуда что нужно, а свои специфичные для авторизации зависимости добавляй в своих модулях». Чисто, модульно, и голова не болит.

Так как же не облажаться? Правила простые, как три копейки:

  1. Дроби по фичам или слоям. Отдельный компонент на авторизацию, отдельный — на фичу «Лента новостей», отдельный — на «Профиль». Не лепи всё в одну кучу. Иначе получится пизда рулю, а не архитектура.
  2. Связывай их грамотно. Либо через сабкомпоненты (это когда дочерний полностью наследует зависимости родителя), либо через dependencies (как в примере выше), где ты явно указываешь, что от чего зависит. Выбор зависит от задачи, но суть одна — не создавай зависимостей из воздуха.
  3. Избегай компонентов-переростков. Если твой компонент выглядит так, будто он съел все модули в проекте, и в нём 150 методов предоставления — это верный знак, что пора его нахуй разбивать. Гигантский компонент — это как хуй с горы: всем мешает, ничего не делает, а проблем от него — вагон и маленькая тележка.

Короче, смысл в том, чтобы твой код был управляемым. Чтобы через полгода ты сам не охуел, глядя на эту паутину зависимостей, и не начал материться, пытаясь добавить новую фичу. Делай много маленьких, понятных компонентов — и жить станет проще. Ну, относительно, конечно. Всё равно придётся иногда ебаться с этой магией, но уже не так жестоко.