Dagger 2 — фреймворк для dependency injection (DI) в Java/Kotlin
Dagger 2 — это инструмент для автоматического внедрения зависимостей, разработанный Google. Он генерирует код на этапе компиляции (без рефлексии), что делает его быстрым и безопасным.
🔥 Основные концепции Dagger 2
1. Dependency Injection (DI)
Паттерн, при котором зависимости (сервисы, репозитории и т.д.) передаются в класс извне, а не создаются внутри него.
Пример без DI:
class Car {
private val engine = Engine() // Прямое создание зависимости
}
Пример с DI:
class Car(private val engine: Engine) // Зависимость внедряется извне
2. Компоненты Dagger 2
@Module
— класс, который предоставляет зависимости (аналог «фабрики»).@Component
— мост между модулями и классами, куда внедряются зависимости.@Inject
— маркирует поле/конструктор, куда нужно внедрить зависимость.
⚡ Пример работы Dagger 2
1. Создаём зависимости
class Engine @Inject constructor() // Dagger сможет создавать Engine
class Car @Inject constructor(private val engine: Engine)
2. Модуль (если зависимость нельзя создать через @Inject
)
@Module
class AppModule {
@Provides
fun provideEngine(): Engine = DieselEngine() // Специальная реализация
}
3. Компонент
@Component(modules = [AppModule::class])
interface AppComponent {
fun inject(activity: MainActivity) // Точка внедрения
}
4. Генерация и использование
Dagger создаст реализацию AppComponent
в момент компиляции:
class MainActivity : AppCompatActivity() {
@Inject lateinit var car: Car // Поле для внедрения
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
DaggerAppComponent.create().inject(this) // Внедрение!
car.start()
}
}
🌟 Преимущества Dagger 2
✔ Нет рефлексии — весь код генерируется на этапе компиляции.
✔ Проверка зависимостей на этапе компиляции (если что-то не сходится — ошибка).
✔ Высокая производительность (оптимизированный код).
✔ Поддержка Kotlin и Java.
📉 Сложности Dagger 2
❌ Сложный входной порог — много новых терминов.
❌ Избыточность для маленьких проектов.
❌ Неудобные ошибки компиляции, если что-то настроено неверно.
🔄 Dagger 2 vs. Koin
Критерий | Dagger 2 | Koin |
---|---|---|
Принцип работы | Генерация кода (компиляция) | Рефлексия + прокси-объекты |
Производительность | ⚡ Быстрее (нет runtime-накладок) | 🐢 Медленнее |
Сложность | Высокая | Низкая |
Поддержка | Java/Kotlin | Только Kotlin |
Когда выбирать Dagger 2?
- В больших проектах, где важна производительность.
- Если уже используется Java.
Когда выбирать Koin?
- Для маленьких/средних Kotlin-проектов.
- Если нужна простота.
🛠 Продвинутые возможности Dagger 2
@Subcomponent
— вложенные компоненты (например, для экранов в Android).@Scope
— контроль времени жизни зависимостей (например,@Singleton
).- Multibinding — внедрение коллекций зависимостей.
Пример с @Singleton
:
@Module
class NetworkModule {
@Singleton // Один экземпляр на всё приложение
@Provides
fun provideApiService(): ApiService = Retrofit.create()
}
📚 Как выучить Dagger 2?
- Официальная документация: dagger.dev.
- Практика:
- Внедрение
SharedPreferences
в Android. - Создание многомодульного приложения с DI.
- Книги:
- «Dependency Injection with Dagger 2» (Google Developers).
🚀 Пример с Android
Внедрение SharedPreferences
@Module
class StorageModule {
@Provides
fun provideSharedPrefs(context: Context): SharedPreferences {
return context.getSharedPreferences("app_prefs", MODE_PRIVATE)
}
}
@Component(modules = [StorageModule::class])
interface AppComponent {
fun inject(activity: SettingsActivity)
}
// Использование:
class SettingsActivity : AppCompatActivity() {
@Inject lateinit var prefs: SharedPreferences
}
💡 Советы по Dagger 2
✔ Старайтесь избегать @Inject
в Android-активностях (лучше использовать ViewModel).
✔ Разделяйте компоненты по функционалу (например, NetworkComponent
, StorageComponent
).
✔ Используйте @Named
для однотипных зависимостей:
@Provides @Named("prod") fun provideProdApi(): Api = ...
@Provides @Named("mock") fun provideMockApi(): Api = ...
🔥 Вывод
Dagger 2 — это мощный инструмент для DI, который:
✅ Уменьшает связанность кода.
✅ Упрощает тестирование.
✅ Ускоряет работу приложения.
Используйте его, если:
- Проект сложный и требует чёткого контроля зависимостей.
- Критична производительность.
Альтернативы:
- Koin (для Kotlin).
- Hilt (упрощённая версия Dagger для Android).