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

Как контролировать жизненный цикл Subcomponent в Dagger

1.7 Middle🔥 201 комментариев
#Жизненный цикл и навигация

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

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

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

Контроль жизненного цикла Subcomponent в Dagger

В Dagger Subcomponent — это компонент, который наследует граф зависимостей родительского Component и может добавлять свои собственные зависимости. Жизненный цикл Subcomponent часто должен быть связан с жизненным циклом объекта, который его создает (например, Activity или Fragment). Контроль этого цикла осуществляется через явное создание и уничтожение.

Основные механизмы контроля

1. Создание Subcomponent через фабричный метод в родительском компоненте

Родительский компонент предоставляет метод для создания Subcomponent. Этот метод обычно принимает модуль, специфичный для scope (области видимости) Subcomponent.

// Родительский компонент (Application scope)
@Component(modules = [AppModule::class])
interface AppComponent {
    // Фабричный метод для создания Subcomponent ActivityComponent
    fun createActivityComponent(activityModule: ActivityModule): ActivityComponent
}

// Subcomponent (Activity scope)
@Subcomponent(modules = [ActivityModule::class])
interface ActivityComponent {
    fun inject(activity: MainActivity)
}

2. Использование Scope (областей видимости) для управления временем жизни

Scope (@ActivityScope, @FragmentScope) определяет, как долго объект существует. Subcomponent должен быть ассоциирован с конкретной областью. Dagger не уничтожает объекты автоматически — время жизни управляется разработчиком.

// Custom scope для Activity
@Scope
@Retention(AnnotationRetention.RUNTIME)
annotation class ActivityScope

// Применение scope к Subcomponent и его зависимостям
@ActivityScope
@Subcomponent
interface ActivityComponent {
    fun inject(activity: MainActivity)
}

@ActivityScope
@Provides
fun provideRepository(api: Api): Repository {
    return RepositoryImpl(api)
}

3. Явное создание и очистка в жизненном цикле Android компонентов

Subcomponent создается в onCreate() Activity/Fragment и должен быть очищен (ссылки отпущены) в onDestroy().

class MainActivity : AppCompatActivity() {
    private lateinit var activityComponent: ActivityComponent

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        
        // Получаем родительский компонент (например, через Application)
        val appComponent = (application as MyApp).appComponent
        
        // Создаем Subcomponent для этой Activity
        activityComponent = appComponent.createActivityComponent(
            ActivityModule(this)
        )
        activityComponent.inject(this)
    }

    override fun onDestroy() {
        super.onDestroy()
        // Явно очищаем ссылку, позволяя Subcomponent и его объектам
        // быть собраны GC, если на них нет других ссылок
        // activityComponent = null // В Kotlin ссылка будет очищена автоматически при уничтожении Activity
    }
}

4. Использование Component Factory для более гибкого создания

В Dagger 2 можно использовать @Component.Factory или @Subcomponent.Factory для создания компонентов с параметрами.

@Subcomponent.Factory
interface Factory {
    fun create(activityModule: ActivityModule): ActivityComponent
}

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

Ключевые принципы и практики

  • Ответственность за жизненный цикл лежит на разработчике: Dagger не управляет временем жизни объектов автоматически. Он только предоставляет граф зависимостей.
  • Scope — это маркер, а не контроллер: Аннотации @Scope лишь указывают, что объект должен существовать определенное время, но не обеспечивают это.
  • Subcomponent живет пока живет его владелец: Если Subcomponent создан для Activity, он должен существовать только в пределах жизни этой Activity. Явная очистка ссылок в onDestroy() критична для предотвращения утечек памяти.
  • Не используйте один Subcomponent для нескольких владельцев: Каждая Activity должна иметь свой собственный экземпляр Subcomponent.
  • Для сложных сценариев рассматривайте чистку зависимостей: Если Subcomponent предоставляет объекты, которые сами требуют очистки (например, соединения с сетью), реализуйте механизм явного освобождения ресурсов.

Альтернативный подход: Custom Scoped Components

Для более строгого контроля можно создавать собственные компоненты с явным управлением жизненным циклом через кастомные менеджеры.

class ActivityComponentManager {
    private val components = mutableMapOf<String, ActivityComponent>()

    fun getOrCreate(activityId: String, factory: ActivityComponent.Factory): ActivityComponent {
        return components.getOrPut(activityId) {
            factory.create(ActivityModule())
        }
    }

    fun remove(activityId: String) {
        components.remove(activityId)
    }
}

Заключение: Контроль жизненного цикла Subcomponent в Dagger сводится к правильной ассоциации с Scope, явному созданию в точке начала жизни владельца (Activity, Fragment) и явной очистке ссылок в конце его жизни. Это предотвращает утечки памяти и обеспечивает корректное управление зависимостями.