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

Как сделать так, чтобы Dagger автоматически затянул объект

1.8 Middle🔥 171 комментариев
#Dependency Injection

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

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

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

Автоматическое внедрение зависимостей с помощью Dagger

Чтобы Dagger автоматически затянул (injected) объект, необходимо правильно настроить компоненты, модули и использовать аннотации. Dagger — это фреймворк для внедрения зависимостей (DI), который генерирует код во время компиляции на основе вашей конфигурации. Вот пошаговое руководство:

1. Создание Module

Модуль предоставляет зависимости. Используйте аннотацию @Module и методы с @Provides или @Binds.

@Module
class AppModule {
    
    @Provides
    fun provideNetworkService(): NetworkService {
        return RetrofitNetworkService()
    }
    
    @Provides
    @Singleton
    fun provideDatabase(): AppDatabase {
        return Room.databaseBuilder(...).build()
    }
}

2. Создание Component

Компонент — это мост между модулями и классами, куда нужно внедрять зависимости. Определите, какие модули включает компонент и какие типы он может внедрять.

@Singleton
@Component(modules = [AppModule::class])
interface AppComponent {
    
    // Метод для внедрения в Activity
    fun inject(activity: MainActivity)
    
    // Фабричный метод для создания компонента
    @Component.Builder
    interface Builder {
        fun build(): AppComponent
    }
}

3. Инициализация Dagger Component

Обычно инициализацию проводят в классе Application.

class MyApp : Application() {
    
    lateinit var appComponent: AppComponent
    
    override fun onCreate() {
        super.onCreate()
        appComponent = DaggerAppComponent.builder()
            .build()
    }
}

4. Внедрение в целевой класс

Для автоматического внедрения:

  • Аннотируйте поля с @Inject
  • Вызовите метод inject() компонента
class MainActivity : AppCompatActivity() {
    
    @Inject
    lateinit var networkService: NetworkService
    
    @Inject
    lateinit var database: AppDatabase
    
    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        
        // Получаем компонент из Application
        (application as MyApp).appComponent.inject(this)
        
        // Теперь зависимости автоматически затянуты и готовы к использованию
        networkService.makeRequest()
    }
}

5. Constructor Injection для собственных классов

Если вы создаете класс, зависимости которого тоже должны внедряться автоматически, используйте constructor injection:

class UserRepository @Inject constructor(
    private val networkService: NetworkService,
    private val database: AppDatabase
) {
    fun getUsers() { ... }
}

Затем Dagger сможет автоматически создать экземпляр UserRepository, когда он потребуется в другом классе.

6. Работа с зависимостями, которые нельзя изменить

Для зависимостей из сторонних библиотек (например, Retrofit, OkHttpClient, Context) используйте @Provides методы в модулях, как показано выше. Для Context часто делают так:

@Module
class AppModule(private val context: Context) {
    
    @Provides
    fun provideContext(): Context = context
}

Ключевые принципы автоматического внедрения:

  • Граф зависимостей: Dagger строит граф зависимостей на основе аннотаций. Он ищет @Inject конструктор или @Provides методы.
  • Скоупы: Используйте @Singleton, @ActivityScope и другие скоупы для управления жизненным циклом объектов.
  • Component dependencies и Subcomponents: Для сложных графов используйте вложенные компоненты.
  • Ленивое внедрение: Используйте Lazy<T> для отложенной инициализации.

Пример с Subcomponent для Activity:

@ActivityScope
@Subcomponent(modules = [ActivityModule::class])
interface ActivityComponent {
    fun inject(activity: MainActivity)
    
    @Subcomponent.Factory
    interface Factory {
        fun create(@BindsInstance activity: Activity): ActivityComponent
    }
}

Затем в AppComponent:

@Singleton
@Component(modules = [AppModule::class])
interface AppComponent {
    fun activityComponentFactory(): ActivityComponent.Factory
}

И в Activity:

class MainActivity : AppCompatActivity() {
    
    @Inject
    lateinit var viewModel: MainViewModel
    
    override fun onCreate(savedInstanceState: Bundle?) {
        val factory = (application as MyApp).appComponent.activityComponentFactory()
        factory.create(this).inject(this)
        super.onCreate(savedInstanceState)
    }
}

Таким образом, Dagger автоматически затянет все зависимости, помеченные @Inject, при условии корректной настройки компонентов и модулей. Это избавляет от ручного создания объектов и упрощает тестирование.

Как сделать так, чтобы Dagger автоматически затянул объект | PrepBro