Когда стоит использовать Inject constructor в Dagger?
Комментарии (1)
Ответ сгенерирован нейросетью и может содержать ошибки
Когда использовать @Inject constructor() в Dagger?
@Inject constructor() — это аннотация, которая сообщает Dagger, как создавать экземпляры класса, когда они требуются в графе зависимостей. Это один из основных способов предоставления зависимостей, наряду с @Provides методами в модулях и @Binds для абстракций. Решение о его использовании основывается на нескольких ключевых факторах.
Основные сценарии использования @Inject constructor
1. Когда класс находится под вашим контролем
Используйте @Inject для классов, исходный код которых вы можете изменить (например, собственные ViewModel, Repository, UseCase). Это самый простой и декларативный способ. Dagger автоматически создаст фабрику для этого класса.
// Правильно: класс под нашим контролем
class UserRepository @Inject constructor(
private val apiService: ApiService,
private val cache: UserCache
) {
fun getUser(id: String): User { ... }
}
2. Для внедрения зависимостей в конструктор
Это предпочтительный способ, соответствующий принципу инверсии зависимостей (Dependency Injection). Все необходимые зависимости явно объявляются в параметрах конструктора, что делает класс тестируемым и независимым от фреймворка.
// Зависимости явно объявлены
class PaymentProcessor @Inject constructor(
private val validator: Validator,
private val gateway: PaymentGateway,
@Named("RetryCount") private val retryCount: Int
)
3. Когда зависимости могут быть предоставлены графом Dagger
Все параметры конструктора, помеченного @Inject, должны быть доступны в графе зависимостей (через другие @Inject конструкторы, @Provides методы или @Component dependencies). Если вы не контролируете какой-то класс (например, библиотечный Retrofit), используйте @Provides.
4. Для избежания boilerplate кода в модулях
@Inject constructor сокращает количество кода. Без него пришлось бы создавать модуль с методом @Provides.
// Вместо этого в модуле:
// @Module
// class AppModule {
// @Provides
// fun provideRepository(api: Api): Repository = RepositoryImpl(api)
// }
// Можно просто:
class RepositoryImpl @Inject constructor(private val api: Api) : Repository
Когда НЕ стоит использовать @Inject constructor
- Классы сторонних библиотек: Вы не можете аннотировать их конструктор. Используйте
@Provides.@Module object NetworkModule { @Provides fun provideOkHttpClient(): OkHttpClient = OkHttpClient.Builder().build() } - Интерфейсы или абстракции: Для них используйте связку
@Bindsв модуле.@Module interface RepositoryModule { @Binds fun bindRepository(impl: UserRepositoryImpl): UserRepository } - Когда логика создания объекта сложная: Если экземпляр нельзя создать простым вызовом конструктора (требуется конфигурация, выбор реализации по условию), используйте
@Provides.@Provides @Named("Cached") fun provideCachedRepository( networkRepo: NetworkRepo, cache: Cache ): Repository = if (cache.isValid) CachedRepo(cache) else networkRepo - Для примитивных типов или строк: Они требуют квалификаторов (например,
@Named) и обычно предоставляются через@Providesв модуле.
Практические рекомендации и вывод
- Отдавайте предпочтение
@Inject constructorдля ваших собственных классов. Это делает код чище и следует конвенции Dagger/Hilt. - Помните о правиле "один аннотированный конструктор": В классе может быть только один конструктор, отмеченный
@Inject. - Используйте
@Injectдля полей (field injection) только когда необходимо, например, для классов Android (Activity, Fragment), где конструкторы недоступны. Но саму зависимость лучше запрашивать в конструкторе. - В Hilt использование
@Inject constructor()становится практически стандартом для внедряемых классов, так как Hilt генерирует все необходимые компоненты автоматически.
Итог: @Inject constructor — ваш основной инструмент для пометки классов, которые Dagger может создавать самостоятельно. Его использование приводит к более чистому, поддерживаемому и тестируемому коду, минимизируя ручную конфигурацию в модулях. Для всех остальных случаев, когда прямое внедрение через конструктор невозможно, применяйте @Provides и @Binds в модулях Dagger.