Что такое Qualifier в Dagger?
Комментарии (1)
Ответ сгенерирован нейросетью и может содержать ошибки
Что такое Qualifier в Dagger
Qualifier в Dagger — это механизм аннотаций, позволяющий различать зависимости одного типа. По сути, это способ сказать Dagger: "Хотя у меня есть несколько объектов одинакового класса, я хочу инъектировать конкретный экземпляр, отмеченный специальной меткой". Это решает проблему, когда Dependency Injection (DI) фреймворк не может определить, какой именно экземпляр предоставить, если в графе зависимостей присутствует несколько объектов одного типа.
Проблематика без использования Qualifier
Рассмотрим классический пример. У нас есть два объекта типа String, которые должны использоваться в разных контекстах.
class UserRepository(
private val apiUrl: String,
private val dbName: String
)
Без Qualifier Dagger увидит два зависимости типа String и не сможет понять, какой String (URL API или имя базы данных) инъектировать в каждое поле. Он попытается найти одну @Provides-функцию, возвращающую String, что приведет к ошибке.
Решение с помощью Qualifier
Для решения создаются custom-аннотации, помеченные @Qualifier. Они служат уникальными "метками" для зависимостей.
1. Определение Qualifier-аннотаций
import javax.inject.Qualifier
@Qualifier
@Retention(AnnotationRetention.RUNTIME)
annotation class ApiUrl
@Qualifier
@Retention(AnnotationRetention.RUNTIME)
annotation class DatabaseName
2. Использование в модуле (Module)
В @Module мы создаем две отдельные функции предоставления, каждая помечена своей Qualifier-аннотацией.
@Module
class NetworkModule {
@Provides
@ApiUrl
fun provideApiUrl(): String {
return "https://api.example.com"
}
}
@Module
class DatabaseModule {
@Provides
@DatabaseName
fun provideDatabaseName(): String {
return "app_database"
}
}
3. Использование при инъекции (Inject)
В целевом классе мы аннотируем параметры конструктора соответствующими Qualifier-аннотациями.
class UserRepository @Inject constructor(
@ApiUrl private val apiUrl: String,
@DatabaseName private val dbName: String
) {
fun fetchData() {
println("Fetching from: $apiUrl")
println("Using database: $dbName")
}
}
Теперь Dagger четко понимает:
- Для поля
apiUrlнужно найти @Provides-метод, также помеченный @ApiUrl. - Для поля
dbName— метод, помеченный @DatabaseName.
Альтернатива: @Named
Dagger также предоставляет стандартный Qualifier @Named, принимающий строковый параметр. Он удобен для простых случаев, но менее выразителен и может привести к ошибкам из-за повторения строк.
import javax.inject.Named
@Module
class AppModule {
@Provides
@Named("apiUrl")
fun provideApiUrl(): String = "https://api.example.com"
@Provides
@Named("dbName")
fun provideDatabaseName(): String = "app_database"
}
class UserRepository @Inject constructor(
@Named("apiUrl") private val apiUrl: String,
@Named("dbName") private val dbName: String
)
Ключевые преимущества использования Qualifier
- Ясность и безопасность: Прямо указывается назначение зависимости, уменьшая путаницу.
- Поддержка множественных экземпляров: Позволяет иметь несколько объектов одного типа в графе DI.
- Улучшенная читаемость кода: Custom Qualifier с понятными названиями (
@ApiUrl,@DefaultDispatcher,@IoDispatcher) делают код самодокументируемым. - Избегание конфликтов: Решает проблему, когда Dagger не может выбрать между несколькими кандидатами одного типа.
Практические примеры применения
Qualifier широко используются в реальных проектах:
- Разные Retrofit клиенты для различных API (
@MainApi,@AuthApi). - Coroutine Dispatchers (
@MainDispatcher,@IoDispatcher,@DefaultDispatcher). - Конфигурационные строки или URL.
- Разные реализации интерфейса (например,
@MockDataSourceи@RealDataSourceдляDataSource).
Вывод
Qualifier — это мощный и необходимый инструмент в Dagger, обеспечивающий точность и контроль в процессе инъекции зависимостей. Он превращает потенциальную ошибку неоднозначности в четко структурированную систему, где каждая зависимость получает уникальную идентификацию. Использование собственных (custom) Qualifier вместо @Named считается best practice, так как повышает читаемость и снижает вероятность ошибок.