Как контролировать жизненный цикл Subcomponent в Dagger
Комментарии (1)
Ответ сгенерирован нейросетью и может содержать ошибки
Контроль жизненного цикла 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) и явной очистке ссылок в конце его жизни. Это предотвращает утечки памяти и обеспечивает корректное управление зависимостями.