Ответ
Количество Dagger компонентов в приложении не ограничено и зависит от архитектуры. Обычно используют:
- Один компонент – для простых приложений (не рекомендуется для больших проектов).
- Множество компонентов – для модульности, разделения зависимостей (например,
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). Бери оттуда что нужно, а свои специфичные для авторизации зависимости добавляй в своих модулях». Чисто, модульно, и голова не болит.
Так как же не облажаться? Правила простые, как три копейки:
- Дроби по фичам или слоям. Отдельный компонент на авторизацию, отдельный — на фичу «Лента новостей», отдельный — на «Профиль». Не лепи всё в одну кучу. Иначе получится пизда рулю, а не архитектура.
- Связывай их грамотно. Либо через сабкомпоненты (это когда дочерний полностью наследует зависимости родителя), либо через
dependencies(как в примере выше), где ты явно указываешь, что от чего зависит. Выбор зависит от задачи, но суть одна — не создавай зависимостей из воздуха. - Избегай компонентов-переростков. Если твой компонент выглядит так, будто он съел все модули в проекте, и в нём 150 методов предоставления — это верный знак, что пора его нахуй разбивать. Гигантский компонент — это как хуй с горы: всем мешает, ничего не делает, а проблем от него — вагон и маленькая тележка.
Короче, смысл в том, чтобы твой код был управляемым. Чтобы через полгода ты сам не охуел, глядя на эту паутину зависимостей, и не начал материться, пытаясь добавить новую фичу. Делай много маленьких, понятных компонентов — и жить станет проще. Ну, относительно, конечно. Всё равно придётся иногда ебаться с этой магией, но уже не так жестоко.