Жизненный цикл в Jetpack Compose — часть Android Jetpack .

Компоненты, учитывающие жизненный цикл, выполняют действия в ответ на изменение статуса жизненного цикла хост-активности. Артефакт androidx.lifecycle.compose предоставляет специальные API, которые автоматически очищают ресурсы, когда они покидают экран или когда приложение переходит в фоновый режим.

К основным API относятся следующие:

Эти интеграции предоставляют удобные точки доступа для управления жизненными циклами в иерархии Compose. В этом документе описано, как вы можете использовать их в своем приложении.

Собирайте данные о состоянии жизненного цикла с помощью потоков.

Lifecycle предоставляет свойство currentStateFlow , которое передает текущее состояние Lifecycle.State в виде StateFlow в Kotlin. Вы можете собирать этот Flow как State . Это позволяет вашему приложению считывать изменения в Lifecycle во время композиции.

val lifecycleOwner = LocalLifecycleOwner.current
val stateFlow = lifecycleOwner.lifecycle.currentStateFlow

val currentLifecycleState by stateFlow.collectAsState()

Приведенный выше пример доступен через модуль lifecycle-common . Метод currentStateAsState() доступен в модуле lifecycle-runtime-compose , что позволяет удобно считывать текущее состояние жизненного цикла одной строкой кода. Следующий пример демонстрирует это:

val lifecycleOwner = LocalLifecycleOwner.current
val currentLifecycleState = lifecycleOwner.lifecycle.currentStateAsState()

Выполнение кода при событиях жизненного цикла

Вместо создания отдельного класса, реализующего интерфейс DefaultLifecycleObserver , и его ручного добавления в жизненный цикл, вы можете объявить логику жизненного цикла непосредственно в коде, используя определенные эффекты. LifecycleEffects позволяет запускать блок кода при возникновении определенного Lifecycle.Event непосредственно внутри композиции.

LifecycleEventEffect

Используйте LifecycleEventEffect для выполнения блока кода при возникновении определенного события. Это лучше всего подходит для разовых событий, таких как логирование или аналитика, где не требуется ни успеха, ни немедленного результата.

@Composable
fun AnalyticsTracker(screenName: String) {
    // Log an event when the app receives ON_RESUME (e.g. comes to foreground)
    LifecycleEventEffect(Lifecycle.Event.ON_RESUME) {
        Analytics.logView(screenName)
    }
}

LifecycleStartEffect

Для парных операций запуска/остановки, которые должны выполняться во время запуска приложения (видимо) и завершаться при его остановке (в фоновом режиме), используйте LifecycleStartEffect .

Подобно другим эффектам Compose (например, LaunchedEffect ), LifecycleStartEffect принимает клавиши. При изменении клавиши блок запускается снова.

Когда происходит событие Lifecycle.Event.ON_STOP или эффект выходит из композиции, выполняется блок onStopOrDispose для очистки всей работы, которая была частью начального блока.

@Composable
fun LocationMonitor(locationManager: LocationManager) {
    // Starts monitoring when ON_START is dispatched
    // Stops monitoring when ON_STOP is dispatched
    //   (or the composable leaves the screen)
    LifecycleStartEffect(locationManager) {
        val listener = LocationListener { location ->
            /* update UI */
        }
        locationManager.requestLocationUpdates(listener)
        // The cleanup block automatically runs on ON_STOP or on disposal
        onStopOrDispose {
            locationManager.removeUpdates(listener)
        }
    }
}

Информацию о других типах побочных эффектов см. в разделе «Побочные эффекты» в Compose .

LifecycleResumeEffect

Эффект LifecycleResumeEffect работает аналогично эффекту LifecycleStartEffect , но привязан к событию Lifecycle.Event.ON_RESUME . Он также предоставляет блок onPauseOrDispose , который выполняет очистку при срабатывании события ON_PAUSE или при выходе составного объекта с экрана.

Этот API полезен для ресурсов, которые должны быть активны только тогда, когда пользователь взаимодействует с приложением, — например, камеры или анимация.

@Composable
fun CameraPreview(cameraController: CameraController) {
    LifecycleResumeEffect(cameraController) {
        cameraController.startPreview()

        onPauseOrDispose {
            cameraController.stopPreview()
        }
    }
}

Получите доступ к LifecycleOwner

В Compose объект LifecycleOwner неявно доступен через CompositionLocal с именем LocalLifecycleOwner . По умолчанию этот владелец предоставляется корневым хостом вашей иерархии композиций.

val lifecycleOwner = LocalLifecycleOwner.current

Для многих приложений достаточно проверить этот владелец по умолчанию или передать его эффектам, учитывающим жизненный цикл. Однако для пользовательской навигации или сложных макетов может потребоваться создать собственный LifecycleOwner , чтобы ограничить состояния жизненного цикла определенными разделами пользовательского интерфейса. Например, библиотеки навигации (такие как Navigation 3 ) делают это автоматически, чтобы каждый отдельный экран имел свой собственный жизненный цикл.

Создайте настраиваемого владельца жизненного цикла.

API rememberLifecycleOwner() позволяет создавать и запоминать пользовательский LifecycleOwner . Это особенно полезно для таких компонентов, как HorizontalPager , где вы хотите, чтобы RESUMED только видимая, завершенная страница, а для соседних страниц, находящихся за пределами экрана, устанавливалось maxState равным STARTED .

val pagerState = rememberPagerState(pageCount = { 10 })

HorizontalPager(state = pagerState) { pageNum ->
    val pageLifecycleOwner = rememberLifecycleOwner(
        maxState = if (pagerState.settledPage == pageNum) {
            Lifecycle.State.RESUMED
        } else {
            Lifecycle.State.STARTED
        }
    )

    CompositionLocalProvider(LocalLifecycleOwner provides pageLifecycleOwner) {
        // Your pages here. Their lifecycle-aware components respect the
        // custom maxState defined above.
    }
}

Для получения дополнительной информации о CompositionLocal см. раздел «Данные с локальной областью видимости, обрабатываемые CompositionLocal» .

Рекомендации по использованию компонентов с учетом жизненного цикла

  • Старайтесь максимально упростить контроллеры пользовательского интерфейса. Они не должны пытаться получать собственные данные; вместо этого используйте для этого ViewModel и отслеживайте объект StateFlow , чтобы отражать изменения обратно в пользовательский интерфейс.
  • Старайтесь создавать пользовательские интерфейсы, управляемые данными, где задача контроллера пользовательского интерфейса состоит в обновлении интерфейса по мере изменения данных или в уведомлении ViewModel о действиях пользователя.
  • Разместите логику обработки данных в классе ViewModel . ViewModel должен служить связующим звеном между контроллером пользовательского интерфейса и остальной частью приложения. Однако будьте осторожны: ViewModel не отвечает за получение данных (например, из сети). Вместо этого ViewModel должен вызывать соответствующий компонент для получения данных, а затем передавать результат обратно контроллеру пользовательского интерфейса.
  • Используйте сопрограммы Kotlin для управления длительными задачами и другими операциями, которые могут выполняться асинхронно.
  • Логику запуска/остановки следует размещать внутри того компонуемого элемента, которому она действительно необходима. Таким образом, эта логика автоматически удаляется, если конкретный элемент пользовательского интерфейса удаляется с экрана (например, внутри навигационной диаграммы или при условной видимости).
  • Используйте collectAsStateWithLifecycle для сбора данных. Не запускайте и не останавливайте сбор Flow вручную на основе событий жизненного цикла. Вместо этого используйте collectAsStateWithLifecycle для эффективного преобразования потоков в состояние пользовательского интерфейса. Это экономит заряд батареи и ресурсы, поскольку Flow приостанавливается, когда приложение находится в фоновом режиме.

Для получения дополнительной информации о Flow см. раздел «Другие поддерживаемые типы состояний» .

Варианты использования компонентов, учитывающих жизненный цикл

Компоненты, учитывающие жизненный цикл, могут значительно упростить управление жизненными циклами в самых разных ситуациях. Вот несколько примеров:

  • Переключение между точным и детализированным обновлением местоположения. Используйте LifecycleStartEffect , чтобы включить детализированное обновление местоположения, пока ваше приложение видимо ( ON_START ), и автоматически очистить обработчик событий или переключиться на точный режим обновления, когда приложение находится в фоновом режиме ( ON_STOP ).
  • Остановка и запуск буферизации видео. Используйте LifecycleResumeEffect , чтобы отложить фактическое воспроизведение видео до тех пор, пока приложение полностью не перейдет в активный режим и не станет интерактивным ( ON_RESUME ), а также чтобы гарантировать приостановку воспроизведения и освобождение ресурсов при переходе приложения в фоновый режим ( ON_PAUSE ).
  • Запуск и остановка потоковой передачи данных по сети. Используйте collectAsStateWithLifecycle для наблюдения за непрерывными потоками данных (подобно Kotlin Flow из сетевого сокета). Это обеспечивает обновление данных в реальном времени, пока приложение находится на переднем плане, и автоматически отменяет сбор данных, когда приложение переходит в фоновый режим.
  • Приостановка и возобновление ресурсоемких задач. Используйте LifecycleResumeEffect для приостановки ресурсоемких визуальных обновлений, когда приложение находится в фоновом режиме, и возобновления их после перевода приложения на передний план.

Безопасная обработка событий ON_STOP

Compose разработан для безопасной обработки событий ON_STOP .

  • Состояние безопасно: вы можете обновлять MutableState (например, с помощью uiState.value = ... ) в любое время, даже когда приложение находится в фоновом режиме. Compose ждет, пока приложение станет видимым, чтобы отобразить изменения.
  • Автоматическая очистка: Благодаря таким эффектам, как LifecycleStartEffect , ваш блок очистки ( onStopOrDispose ) запускается ровно тогда, когда жизненный цикл переходит в STOPPED . Это предотвращает задержку ресурсоемких приложений (например, камеры или местоположения) во время работы приложения в фоновом режиме.

Для получения дополнительной информации о MutableState см. раздел «State и Jetpack Compose» .

Дополнительные ресурсы

Чтобы узнать больше об управлении жизненными циклами с помощью компонентов, учитывающих жизненный цикл, обратитесь к следующим дополнительным ресурсам.

Просмотры контента

{% verbatim %} {% endverbatim %} {% verbatim %} {% endverbatim %}