Комментарии (2)
Ответ сгенерирован нейросетью и может содержать ошибки
Добавление объекта в Dagger
В Dagger добавление объекта (или зависимости) для внедрения осуществляется путем объявления его в модуле (Module) или с использованием аннотации @Inject непосредственно в классе. Основной механизм — это создание провайдера (Provider), который сообщает Dagger, как создавать и предоставлять необходимый тип.
Основные подходы
1. Использование модулей с аннотацией @Provides
Модуль — это класс, аннотированный @Module, который содержит методы, аннотированные @Provides. Эти методы определяют, как создаются зависимости.
@Module
class NetworkModule {
@Provides
fun provideOkHttpClient(): OkHttpClient {
return OkHttpClient.Builder()
.connectTimeout(30, TimeUnit.SECONDS)
.readTimeout(30, TimeUnit.SECONDS)
.build()
}
@Provides
fun provideRetrofit(client: OkHttpClient): Retrofit {
return Retrofit.Builder()
.baseUrl("https://api.example.com/")
.client(client)
.addConverterFactory(GsonConverterFactory.create())
.build()
}
}
В этом примере:
- Метод
provideOkHttpClient()предоставляет экземплярOkHttpClient. - Метод
provideRetrofit()принимаетOkHttpClientкак параметр (Dagger автоматически внедрит его) и предоставляетRetrofit.
2. Использование аннотации @Inject в конструкторе класса
Если класс имеет конструктор, аннотированный @Inject, Dagger может создавать его экземпляры напрямую, без необходимости явного провайдера в модуле. Это работает для классов, которые Dagger может инстанцировать самостоятельно (например, не интерфейсы или классы из сторонних библиотек).
class UserRepository @Inject constructor(
private val apiService: ApiService,
private val localDatabase: UserDatabase
) {
// ... логика репозитория
}
Здесь Dagger будет пытаться создать UserRepository, предоставив ему ApiService и UserDatabase. Для этого сами ApiService и UserDatabase также должны быть доступны Dagger (через @Inject в их конструкторах или через @Provides методы).
3. Внедрение через поля и методы (Field & Method Injection)
Если класс не может использовать инъекцию через конструктор (например, класс Activity в Android создается системой), можно использовать инъекцию в поля или методы.
class MainActivity : AppCompatActivity() {
@Inject
lateinit var userRepository: UserRepository
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
// Внедрение должно быть triggered, например, через вызов метода компонента.
DaggerAppComponent.create().inject(this)
// После этого userRepository будет доступен и проинициализирован.
}
}
Для этого в компоненте (Component) должен быть объявлен метод инъекции.
@Component(modules = [NetworkModule, RepositoryModule])
interface AppComponent {
fun inject(activity: MainActivity)
}
Практический пример: Полный цикл добавления объекта
Рассмотрим добавление ApiService (интерфейс), который зависит от Retrofit.
Шаг 1: Определяем модуль, который предоставляет Retrofit и ApiService.
@Module
interface NetworkModule {
@Binds
fun bindApiService(impl: DefaultApiService): ApiService
companion object {
@Provides
fun provideRetrofit(): Retrofit {
return Retrofit.Builder()
.baseUrl("https://api.example.com/")
.addConverterFactory(GsonConverterFactory.create())
.build()
}
@Provides
fun provideDefaultApiService(retrofit: Retrofit): DefaultApiService {
return retrofit.create(DefaultApiService::class.java)
}
}
}
Шаг 2: Создаем компонент, который включает модуль.
@Component(modules = [NetworkModule])
interface ApplicationComponent {
fun getApiService(): ApiService // Для предоставления зависимости напрямую.
fun inject(activity: MainActivity) // Для field injection.
}
Шаг 3: Используем компонент для получения зависимости.
// В Activity через field injection:
class MainActivity : AppCompatActivity() {
@Inject
lateinit var apiService: ApiService
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
DaggerApplicationComponent.create().inject(this)
// Используем apiService
}
}
// Или напрямую через компонент:
val apiService = DaggerApplicationComponent.create().getApiService()
Ключевые термины и аннотации
- @Module: Объявляет класс как модуль, предоставляющий зависимости.
- @Provides: Метод внутри модуля, который создает и возвращает конкретный объект.
- @Inject: Аннотация для конструктора, поля или метода, указывающая, что зависимость должна быть внедрена.
- @Component: Интерфейс или абстрактный класс, который является точкой внедрения. Компонент связывает модули и инъекционные цели.
- @Binds: Используется в абстрактных модулях для связывания реализации с интерфейсом (эффективнее, чем @Provides, когда не требуется сложная логика создания).
- @Singleton и другие Scope аннотации: Для управления жизненным циклом объекта (например, чтобы обеспечить единственный экземпляр в пределах скоупа).
Таким образом, добавление объекта в Dagger сводится к правильной декомпозиции зависимостей и объявлению их провайдеров в модулях или через аннотации в классах. Это позволяет Dagger построить граф зависимостей и автоматически осуществлять инъекцию.