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

Как контролировать жизненный цикл своего компонента в Hilt

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

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

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

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

Управление жизненным циклом компонентов в Hilt

В Hilt управление жизненным циклом компонентов осуществляется через scopes (области видимости). Hilt автоматически связывает созданные компоненты с жизненным циклом стандартных Android-компонентов, таких как Application, Activity, Fragment и View. Основная идея заключается в том, что объекты, внедряемые через Hilt, живут ровно столько, сколько живет компонент, к области видимости которого они привязаны.

Основные компоненты Hilt и их область видимости

Hilt предоставляет предопределенные компоненты, каждый из которых связан с конкретным Android-компонентом и имеет свою область видимости:

  1. SingletonComponent (аннотация @Singleton): привязан к жизненному циклу Application. Объекты в этой области живут всё время жизни приложения.
  2. ActivityRetainedComponent (аннотация @ActivityRetainedScoped): переживает изменения конфигурации (например, поворот экрана), но уничтожается, когда Activity окончательно завершается.
  3. ActivityComponent (аннотация @ActivityScoped): привязан к жизненному циклу Activity. Объекты создаются заново при каждом изменении конфигурации.
  4. ViewModelComponent (аннотация @ViewModelScoped): привязан к жизненному циклу ViewModel. Позволяет иметь один экземпляр зависимости на ViewModel.
  5. FragmentComponent (аннотация @FragmentScoped): привязан к жизненному циклу Fragment.
  6. ViewComponent (аннотация @ViewScoped): привязан к жизненному циклу View.
  7. 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). В этом случае можно создать пользовательскую область видимости.

  1. Создайте аннотацию области видимости:

    @Scope
    @MustBeDocumented
    @Retention(AnnotationRetention.RUNTIME)
    annotation class UserSessionScoped
    
  2. Создайте кастомный компонент 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 сводится к грамотному выбору или созданию подходящей области видимости для каждой зависимости, что позволяет эффективно управлять памятью и временем жизни объектов в вашем приложении.

Как контролировать жизненный цикл своего компонента в Hilt | PrepBro