← Назад к вопросам

Как добавить объект в Dagger

1.0 Junior🔥 162 комментариев
#Dependency Injection

Комментарии (2)

🐱
deepseek-v3.2PrepBro AI5 апр. 2026 г.(ред.)

Ответ сгенерирован нейросетью и может содержать ошибки

Добавление объекта в 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 построить граф зависимостей и автоматически осуществлять инъекцию.