Как контролировать жизненный цикл своего компонента в Hilt
Комментарии (1)
Ответ сгенерирован нейросетью и может содержать ошибки
Управление жизненным циклом компонентов в Hilt
В Hilt управление жизненным циклом компонентов осуществляется через scopes (области видимости). Hilt автоматически связывает созданные компоненты с жизненным циклом стандартных Android-компонентов, таких как Application, Activity, Fragment и View. Основная идея заключается в том, что объекты, внедряемые через Hilt, живут ровно столько, сколько живет компонент, к области видимости которого они привязаны.
Основные компоненты Hilt и их область видимости
Hilt предоставляет предопределенные компоненты, каждый из которых связан с конкретным Android-компонентом и имеет свою область видимости:
SingletonComponent(аннотация@Singleton): привязан к жизненному циклуApplication. Объекты в этой области живут всё время жизни приложения.ActivityRetainedComponent(аннотация@ActivityRetainedScoped): переживает изменения конфигурации (например, поворот экрана), но уничтожается, когдаActivityокончательно завершается.ActivityComponent(аннотация@ActivityScoped): привязан к жизненному циклуActivity. Объекты создаются заново при каждом изменении конфигурации.ViewModelComponent(аннотация@ViewModelScoped): привязан к жизненному циклуViewModel. Позволяет иметь один экземпляр зависимости наViewModel.FragmentComponent(аннотация@FragmentScoped): привязан к жизненному циклуFragment.ViewComponent(аннотация@ViewScoped): привязан к жизненному циклуView.ViewWithFragmentComponentиServiceComponentдля соответствующих типов.
Как задать область видимости для зависимости
Область видимости задается путем аннотирования @Provides-метода в модуле или @Inject конструктора самого класса соответствующей аннотацией области (scope). Зависимость будет существовать в рамках того компонента, область видимости которого указана, и будет переиспользоваться (как синглтон) внутри этого компонента.
// Пример: репозиторий, который должен жить всё время жизни приложения
@Singleton
class UserRepository @Inject constructor(
private val apiService: ApiService,
private val userDao: UserDao
) {
// ... логика репозитория
}
// Или через модуль
@Module
@InstallIn(SingletonComponent::class)
object DatabaseModule {
@Provides
@Singleton // Объект будет создан один раз для SingletonComponent (Application)
fun provideAppDatabase(@ApplicationContext context: Context): AppDatabase {
return Room.databaseBuilder(
context,
AppDatabase::class.java, "app-database"
).build()
}
}
// Пример: зависимость, уникальная для конкретного экрана (Activity)
@ActivityScoped
class NavigationManager @Inject constructor(
private val activity: FragmentActivity
) {
fun navigateTo(destination: Int) {
// Навигация, использующая конкретную Activity
}
}
Создание кастомных областей видимости
Хотя Hilt предоставляет богатый набор предопределенных областей, иногда требуется привязать время жизни зависимости к нестандартному компоненту (например, к пользовательской сессии или экрану внутри BottomSheetDialogFragment). В этом случае можно создать пользовательскую область видимости.
-
Создайте аннотацию области видимости:
@Scope @MustBeDocumented @Retention(AnnotationRetention.RUNTIME) annotation class UserSessionScoped -
Создайте кастомный компонент Hilt, наследующий от более крупного.
Компоненты Hilt организованы в иерархию. Кастомный компонент должен быть установлен (`@InstallIn`) в родительский.
```kotlin
@Scope
@Retention(AnnotationRetention.RUNTIME)
annotation class FeatureScope
// Определяем компонент. Он будет дочерним для ActivityComponent.
// Объекты в FeatureComponent могут зависеть от объектов в ActivityComponent и выше.
@FeatureScope
@Subcomponent
interface FeatureComponent {
// Фабрика для создания экземпляра компонента
@Subcomponent.Factory
interface Factory {
fun create(): FeatureComponent
}
// Метод для внедрения зависимостей в целевой класс
fun inject(feature: MyCustomFeature)
}
```
3. Создайте модуль для установки компонента и определите зависимости с новой областью.
```kotlin
@Module
@InstallIn(FeatureComponent::class) // Устанавливаем модуль в наш кастомный компонент
object FeatureModule {
@Provides
@FeatureScope // Зависимость будет жить в рамках FeatureComponent
fun provideFeatureDependency(): FeatureDependency {
return FeatureDependencyImpl()
}
}
```
4. Получайте экземпляр кастомного компонента там, где это необходимо (например, в Activity), через @EntryPoint и используйте его для внедрения.
```kotlin
// Создаем точку входа для получения фабрики нашего компонента из ActivityComponent
@EntryPoint
@InstallIn(ActivityComponent::class)
interface FeatureComponentEntryPoint {
fun featureComponentFactory(): FeatureComponent.Factory
}
class MainActivity : AppCompatActivity() {
// Получаем фабрику через EntryPoint
private val featureComponent: FeatureComponent by lazy {
EntryPointAccessors.fromActivity(
this,
FeatureComponentEntryPoint::class.java
).featureComponentFactory().create()
}
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
// Внедряем зависимости в кастомный объект
val myFeature = MyCustomFeature()
featureComponent.inject(myFeature)
}
}
```
Ключевые принципы управления жизненным циклом
- Иерархия компонентов: Компоненты Hilt образуют иерархию, где дочерний компонент может получать доступ ко всем зависимостям родительского. Например,
ActivityComponentявляется дочерним дляSingletonComponent. Это значит, чтоActivityможет внедрить объект с областью@Singleton, но не наоборот. - Создание компонентов: Hilt создает компоненты автоматически в соответствующие моменты жизненного цикла Android. Вам не нужно вызывать
create()илиdestroy()вручную. - Освобождение ресурсов: Когда Android уничтожает компонент (например,
Activity), Hilt уничтожает соответствующий компонент и все объекты в его области видимости. Если ваши зависимости требуют очистки (например, закрытие соединений), используйте callback-методы жизненного цикла (например,@OnLifecycleEvent) внутри класса зависимости или очищайте ресурсы вViewModelс помощьюonCleared(). - Избегайте утечек памяти: Самый частый риск — случайно привязать зависимость с более широкой областью видимости (например,
@Singleton) к объекту с более короткой жизнью (например,Activity). Это может привести к утечке памяти, если синглтон хранит ссылку наContextактивности. Всегда используйте@ApplicationContextдля внедрения контекста приложения в синглтоны.
Таким образом, контроль жизненного цикла в Hilt сводится к грамотному выбору или созданию подходящей области видимости для каждой зависимости, что позволяет эффективно управлять памятью и временем жизни объектов в вашем приложении.