Жизненный цикл объекта activity

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

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

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

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

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

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

Информацию об управлении жизненным циклом, в том числе рекомендации по его оптимизации, можно найти в статьях Жизненный цикл в Jetpack Compose и Сохранение состояния интерфейса. Чтобы узнать, как создать надежное приложение производственного качества, используя компоненты архитектуры в сочетании с действиями, ознакомьтесь с руководством по архитектуре приложений.

Концепции жизненного цикла Activity

Для перехода между этапами жизненного цикла объекта activity класс Activity предоставляет шесть основных обратных вызовов: onCreate, onStart, onResume, onPause, onStop и onDestroy. Система вызывает каждый из этих обратных вызовов, когда действие переходит в новое состояние.

На рисунке 1 представлена визуализация этой парадигмы.

Рисунок 1. Упрощенная иллюстрация жизненного цикла объекта Activity.

Когда пользователь начинает покидать объект activity, система вызывает методы для его закрытия. В некоторых случаях активность удаляется из памяти лишь частично, например когда пользователь переключается на другое приложение. В таких случаях активность может вернуться на передний план.

Если пользователь вернется к действию, оно будет продолжено с того места, где он остановился. За некоторыми исключениями, приложениям запрещено запускать действия, когда они работают в фоновом режиме.

Вероятность того, что система завершит определенный процесс вместе с действиями в нем, зависит от состояния действия на момент завершения. Подробнее о том, как состояние связано с вероятностью выгрузки, рассказывается в разделе Состояние активности и выгрузка из памяти.

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

Compose и жизненный цикл

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

  • Коллекция с учетом жизненного цикла: используйте collectAsStateWithLifecycle, чтобы получать потоки из ViewModel. Этот API автоматически начинает сбор данных, когда интерфейс переходит в состояние "Запущен", и останавливает его, когда интерфейс переходит в фоновый режим. Это позволяет избежать ненужного потребления ресурсов. После того как вы соберете поток как состояние, вы сможете использовать LifecycleEffects для выполнения кода при возникновении события жизненного цикла.
  • Логика работы. Используя эти API, интерфейс реагирует на состояние жизненного цикла естественным образом через дерево композиции, гарантируя, что бизнес-логика выполняется только тогда, когда пользователь активно взаимодействует с компонентом.

Подробнее о Compose и жизненном цикле можно узнать в статье Жизненный цикл в Jetpack Compose.

Обратные вызовы жизненного цикла

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

Некоторые действия относятся к методам жизненного цикла объекта Activity. Однако код, реализующий действия зависимого компонента, следует размещать в самом компоненте, а не в методе жизненного цикла объекта activity. Чтобы этого добиться, нужно сделать зависимый компонент поддерживающим жизненный цикл. Чтобы узнать, как сделать зависимые компоненты совместимыми с жизненным циклом, ознакомьтесь с разделом Жизненный цикл в Jetpack Compose.

onCreate

Этот обратный вызов должен быть реализован. Он срабатывает, когда система впервые создает действие. После создания действие переходит в статус Создано. В методе onCreate реализуйте базовую логику запуска приложения, которая выполняется только один раз за весь жизненный цикл активности.

Например, при реализации onCreate можно привязать данные к спискам, связать действие с ViewModel и создать экземпляры некоторых переменных области видимости класса. Этот метод получает параметр savedInstanceState, который представляет собой объект Bundle, содержащий ранее сохраненное состояние операции. Если действие никогда не существовало, значение объекта Bundle будет нулевым.

Если у вас есть компонент с поддержкой жизненного цикла, подключенный к жизненному циклу вашего действия, он получит событие ON_CREATE. Метод, аннотированный @OnLifecycleEvent, вызывается, чтобы компонент, учитывающий жизненный цикл, мог выполнить код настройки, необходимый для состояния created.

В примере ниже показано, как интегрировать composable-функцию Text в минимальный набор Activity:

class ExampleActivity : ComponentActivity() {
    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)

        setContent { // In here, we can call composables!
            MaterialTheme {
                Greeting(name = "compose")
            }
        }
    }
}

@Composable
fun Greeting(name: String) {
    Text(text = "Hello $name!")
}

Ваше действие не остается в состоянии "Создано". После завершения выполнения метода onCreate объект activity переходит в состояние Started, и система быстро вызывает методы onStart и onResume.

onStart

Когда объект activity переходит в состояние Started, система вызывает метод onStart. Этот вызов делает действие видимым для пользователя, пока приложение готовится к тому, чтобы действие перешло в активный режим и стало интерактивным. Например, в этом методе инициализируется код, который поддерживает интерфейс.

Когда объект Activity переходит в состояние "Запущено", любой компонент, связанный с жизненным циклом объекта Activity, получает событие ON_START.

Метод onStart выполняется быстро, и, как и в случае с состоянием Created, активность не остается в состоянии Started. После завершения этого обратного вызова объект activity переходит в состояние Возобновлено, и система вызывает метод onResume.

onResume

Когда объект activity переходит в состояние "Возобновлено", он становится активным, и система вызывает обратный вызов onResume. Это состояние, в котором приложение взаимодействует с пользователем. Приложение остается в этом состоянии, пока что-то не переключит фокус на другое приложение, например входящий звонок, переход пользователя к другому действию или отключение экрана устройства.

Когда активность переходит в состояние "Возобновлено", любой компонент, связанный с ее жизненным циклом, получает событие ON_RESUME. Здесь компоненты жизненного цикла могут включить любую функцию, которая должна работать, пока компонент виден и находится на переднем плане, например запустить предварительный просмотр камеры.

Когда происходит событие, прерывающее работу, объект activity переходит в состояние Paused, и система вызывает обратный вызов onPause.

Если объект activity возвращается из состояния Paused в состояние Resumed, система снова вызывает метод onResume. Поэтому реализуйте onResume, чтобы инициализировать компоненты, которые вы освобождаете во время onPause, и выполнить другие инициализации, которые должны происходить каждый раз, когда активность переходит в состояние "Возобновлено".

Ниже приведен пример компонента с поддержкой жизненного цикла, который получает доступ к камере, когда компонент получает событие ON_RESUME:

class CameraComponent : LifecycleObserver {
    ...
    @OnLifecycleEvent(Lifecycle.Event.ON_RESUME)
    fun initializeCamera() {
        if (camera == null) {
            getCamera()
        }
    }
    ...
}

Приведенный выше код инициализирует камеру, когда LifecycleObserver получает событие ON_RESUME. Однако в многооконном режиме ваши действия могут быть полностью видны, даже если они приостановлены. Например, если приложение работает в многооконном режиме и пользователь нажимает на окно, в котором нет вашего действия, оно переходит в состояние "Приостановлено".

Если вы хотите, чтобы камера была активна только тогда, когда приложение возобновлено (видимо и активно на переднем плане), инициализируйте камеру после события ON_RESUME, как показано выше. Если вы хотите, чтобы камера оставалась активной, когда действие приостановлено, но видно, например в многооконном режиме, инициализируйте камеру после события ON_START.

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

Поэтому тщательно продумайте, на каком этапе жизненного цикла лучше всего взять под контроль общие системные ресурсы в контексте многооконного режима. Подробнее о поддержке многооконного режима рассказывается в статье Поддержка многооконного режима.

Независимо от того, какое событие вы выберете для инициализации, обязательно используйте соответствующее событие жизненного цикла, чтобы освободить ресурс. Если вы инициализируете что-то после события ON_START, освободите или завершите это после события ON_STOP. Если инициализация выполняется после события ON_RESUME, освобождение должно выполняться после события ON_PAUSE.

В приведенном выше фрагменте кода код инициализации камеры помещен в компонент с поддержкой жизненного цикла. Вместо этого вы можете поместить этот код непосредственно в обратные вызовы жизненного цикла объекта activity, например onStart и onStop, но мы не рекомендуем этого делать. Добавив эту логику в независимый компонент с поддержкой жизненного цикла, вы сможете использовать его в нескольких действиях без необходимости дублировать код. Чтобы узнать, как создать компонент с учетом жизненного цикла, ознакомьтесь с разделом Жизненный цикл в Jetpack Compose.

onPause

Система вызывает этот метод, когда пользователь покидает ваше приложение. Однако это не всегда означает, что активность будет уничтожена. Это означает, что активность больше не находится на переднем плане, но все ещё видна, если пользователь работает в многооконном режиме. Вот несколько причин, по которым действие может перейти в это состояние:

  • Событие, которое прерывает выполнение приложения, как описано в разделе об обратном вызове onResume, приостанавливает текущее действие. Это самый распространенный случай.
  • В многооконном режиме в любой момент времени фокус имеет только одно приложение, а все остальные приостанавливаются.
  • При открытии нового полупрозрачного окна, например диалогового окна, действие, которое оно закрывает, приостанавливается. Если окно приложения частично видно, но не находится в фокусе, оно остается в приостановленном состоянии.

Когда активность переходит в состояние "Приостановлено", любой компонент, связанный с ее жизненным циклом, получает событие ON_PAUSE. Именно здесь компоненты жизненного цикла могут остановить любые функции, которые не должны выполняться, когда компонент не находится на переднем плане, например остановить предварительный просмотр камеры.

Используйте метод onPause, чтобы приостановить или скорректировать операции, которые не могут продолжаться или могут продолжаться в ограниченном режиме, пока Activity находится в состоянии "Приостановлено", и которые вы планируете возобновить в ближайшее время.

Вы также можете использовать метод onPause, чтобы освободить системные ресурсы, дескрипторы датчиков (например, GPS) или любые ресурсы, которые влияют на время работы от батареи, когда ваше действие приостановлено и пользователю они не нужны.

Однако, как уже упоминалось в разделе о onResume, приостановленное действие может быть полностью видимым, если приложение работает в многооконном режиме. Чтобы полностью освободить или скорректировать ресурсы и операции, связанные с интерфейсом, для поддержки многооконного режима, используйте onStop вместо onPause.

В следующем примере LifecycleObserver реагирует на событие ON_PAUSE. Это аналог предыдущего примера с событием ON_RESUME, в котором камера, инициализированная после получения события ON_RESUME, освобождается:

class CameraComponent : LifecycleObserver {
    ...
    @OnLifecycleEvent(Lifecycle.Event.ON_PAUSE)
    fun releaseCamera() {
        camera?.release()
        camera = null
    }
    ...
}

В этом примере код освобождения камеры размещен после того, как LifecycleObserver получит событие ON_PAUSE.

Выполнение onPause очень короткое, и его может быть недостаточно для сохранения данных. Поэтому не используйте onPause для сохранения данных приложения или пользовательских данных, выполнения сетевых вызовов или транзакций с базами данных. Такая работа может не завершиться до того, как метод будет выполнен.

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

Завершение метода onPause не означает, что действие выходит из состояния "Приостановлено". Вместо этого действие остается в этом состоянии, пока не возобновится или не станет полностью невидимым для пользователя. Если объект activity возобновляет работу, система снова вызывает обратный вызов onResume.

Если объект activity возвращается из состояния "Приостановлено" в состояние "Возобновлено", система сохраняет экземпляр Activity в памяти и вызывает его, когда система вызывает onResume. В этом случае вам не нужно повторно инициализировать компоненты, созданные во время любого из методов обратного вызова, которые привели к состоянию Resumed. Если объект activity становится полностью невидимым, система вызывает метод onStop.

onStop

Когда ваше действие становится невидимым для пользователя, оно переходит в состояние Stopped, и система вызывает обратный вызов onStop. Это может произойти, когда новое запущенное действие занимает весь экран. Система также вызывает метод onStop, когда объект activity завершает работу и готовится к уничтожению.

Когда объект Activity переходит в состояние Stopped, любой компонент, связанный с его жизненным циклом, получает событие ON_STOP. Именно здесь компоненты жизненного цикла могут останавливать любые функции, которые не должны выполняться, когда компонент не виден на экране.

При использовании метода onStop освобождайте или корректируйте ресурсы, которые не нужны, когда приложение не видно пользователю. Например, приложение может приостановить анимацию или перейти от точного определения местоположения к приблизительному. Использование onStop вместо onPause означает, что работа, связанная с интерфейсом, продолжается, даже когда пользователь просматривает ваши действия в многооконном режиме.

Кроме того, используйте onStop для выполнения относительно ресурсоемких операций завершения работы. Например, если вы не можете найти более подходящее время для сохранения информации в базе данных, вы можете сделать это во время onStop. В примере ниже показана реализация onStop, которая сохраняет содержимое черновика заметки в постоянное хранилище:

override fun onStop() {
    super.onStop()

    // Delegate the save operation to the ViewModel, which handles the
    // background thread operations (e.g., using Kotlin Coroutines and Room).
    noteViewModel.saveDraft()
}

Когда активность переходит в состояние Stopped, объект Activity остается в памяти. Он сохраняет все данные и информацию о членах, но не привязан к менеджеру окон. Когда активность возобновляется, он извлекает эту информацию.

Из состояния "Остановлено" приложение либо возвращается к взаимодействию с пользователем, либо завершает работу и закрывается. Если объект activity возвращается, система вызывает метод onRestart. Если Activity завершит работу, система вызовет onDestroy.

onDestroy

onDestroy вызывается до уничтожения действия. Система вызывает эту функцию обратного вызова по одной из двух причин:

  1. Действие завершается, поскольку пользователь полностью закрыл его или в нем был вызван метод finish.
  2. Система временно уничтожает активность из-за изменения конфигурации, например при повороте устройства или переходе в многооконный режим.

Когда активность переходит в состояние уничтожения, любой компонент, связанный с ее жизненным циклом, получает событие ON_DESTROY. Здесь компоненты жизненного цикла могут удалить все, что им нужно, прежде чем Activity будет уничтожен.

Вместо того чтобы использовать логику в Activity для определения причины уничтожения, используйте объект ViewModel, чтобы хранить данные представления, относящиеся к Activity. Если Activity воссоздается из-за изменения конфигурации, ViewModel не нужно ничего делать, поскольку он сохраняется и передается следующему экземпляру Activity.

Если Activity не будет воссоздан, то у ViewModel будет вызван метод onCleared, в котором он может очистить все необходимые данные перед уничтожением. Различить эти два сценария можно с помощью метода isFinishing.

Если операция завершается, onDestroy – это последний обратный вызов жизненного цикла, который получает операция. Если onDestroy вызывается в результате изменения конфигурации, система немедленно создает новый экземпляр действия, а затем вызывает onCreate в этом новом экземпляре в новой конфигурации.

Функция обратного вызова onDestroy освобождает все ресурсы, не освобожденные более ранними функциями обратного вызова, например onStop.

Состояние объекта activity и выгрузка из памяти

Система завершает процессы, когда ей нужно освободить ОЗУ. Вероятность того, что система завершит определенный процесс, зависит от его состояния в момент завершения. Статус процесса, в свою очередь, зависит от статуса действия, выполняемого в процессе. В таблице 1 показаны взаимосвязи между состоянием процесса, состоянием объекта activity и вероятностью того, что система завершит процесс. Эта таблица применяется только в том случае, если процесс не выполняет другие типы компонентов приложения.

Вероятность гибели

Состояние процесса

Конечный статус действия

Самый низкий

Передний план (имеет или скоро получит фокус)

Возобновление

Низкий

Виден (не в фокусе)

Запущено/приостановлено

Более высокое

Фон (невидимый)

Остановлено

Самый высокий

Пусто

Удалено

Таблица 1. Связь между жизненным циклом процесса и состоянием объекта Activity.

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

Пользователь также может завершить процесс, используя менеджер приложений в разделе "Настройки".

Подробнее о процессах и потоках…

Сохранение и восстановление временного состояния интерфейса

Пользователь ожидает, что состояние интерфейса приложения останется прежним при изменении конфигурации, например при повороте экрана или переходе в многооконный режим. Однако по умолчанию система уничтожает объект activity при изменении конфигурации, удаляя все данные о состоянии интерфейса, хранящиеся в экземпляре объекта activity.

Пользователь ожидает, что состояние интерфейса останется прежним, если он временно переключится на другое приложение, а затем вернется к вашему. Однако система может уничтожить процесс вашего приложения, пока пользователь неактивен и ваше действие остановлено.

Если ограничения системы приводят к уничтожению действия, сохраните временное состояние интерфейса пользователя, используя сочетание ViewModel (для сложной бизнес-логики и состояния экрана), Jetpack Compose rememberSaveable API (для простого состояния интерфейса) и/или локальное хранилище. Чтобы узнать больше о том, как сохранить данные о состоянии сложного интерфейса при завершении процесса или действиях, инициированных системой, ознакомьтесь с разделом Сохранение состояния интерфейса.

rememberSaveable автоматически сохраняет состояние при изменении конфигурации и завершении процесса системой, поэтому вам не нужно писать шаблонный код на уровне действий.

Состояние экземпляра

Существует несколько сценариев, при которых активность уничтожается из-за нормального поведения приложения, например когда пользователь нажимает кнопку "Назад" или когда активность сама сигнализирует о своем уничтожении, вызывая метод finish.

Когда активность уничтожается, потому что пользователь нажимает кнопку "Назад" или активность завершается сама, как системное, так и пользовательское представление об этом экземпляре Activity исчезает навсегда. В таких случаях ожидания пользователя совпадают с поведением системы, и вам не нужно ничего делать.

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

Сохраненные данные, которые система использует для восстановления предыдущего состояния, называются состоянием экземпляра. По сути, это набор пар "ключ-значение". По умолчанию система использует состояние экземпляра, чтобы сохранять основную информацию о макете пользовательского интерфейса, например введенный пользователем текст или положение прокрутки.

Вы можете использовать rememberSaveable, чтобы изменить поведение системы. Если экземпляр действия уничтожается и создается заново, любое состояние интерфейса, заключенное в rememberSaveable, автоматически восстанавливается без необходимости добавлять код на уровне действия.

Однако в вашем приложении, скорее всего, будет более сложная информация о состоянии, которую вы захотите восстановить, например пользовательские данные, ответы сети или переменные-члены, отслеживающие прогресс пользователя. Механизм сохранения состояния экземпляра (и, как следствие, rememberSaveable) не подходит для хранения большого объема данных, поскольку требует сериализации в основном потоке и потребляет память системного процесса.

Чтобы сохранить значительный объем данных, используйте постоянное локальное хранилище, класс ViewModel и подъем состояния Compose, как описано в разделе Сохранение состояния интерфейса.

Сохраняйте простое состояние интерфейса с помощью rememberSaveable

Когда действие начинает останавливаться, система готовится сохранить информацию о состоянии в пакет состояния экземпляра. Чтобы использовать такое поведение системы, вы можете напрямую применять rememberSaveable в своих функциях, созданных с помощью Compose. rememberSaveable автоматически сохраняет и восстанавливает временное состояние интерфейса, например введенный пользователем текст или положение прокрутки, при воссоздании активности.

Чтобы сохранить пользовательские данные о состоянии (например, прогресс в игре), объявите состояние с помощью rememberSaveable. Фреймворк Compose обрабатывает сериализацию в пакет состояния экземпляра:

var userTypedQuery by rememberSaveable(typedQuery, stateSaver = TextFieldValue.Saver) {
    mutableStateOf(
        TextFieldValue(text = typedQuery, selection = TextRange(typedQuery.length))
    )
}

Чтобы сохранить постоянные данные, например настройки пользователя или данные для базы данных, используйте подходящие возможности, когда ваше приложение находится на переднем плане. Если такой возможности нет, сохраните постоянные данные в методе onStop.

Как восстановить состояние интерфейса активности с помощью сохраненного состояния экземпляра

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

var userTypedQuery by rememberSaveable(typedQuery, stateSaver = TextFieldValue.Saver) {
    mutableStateOf(
        TextFieldValue(text = typedQuery, selection = TextRange(typedQuery.length))
    )
}

Действия и навигация

Приложение может много раз переключаться между экранами, например когда пользователь нажимает кнопку "Назад" или выбирает новый пункт назначения. В современных приложениях Android обычно используется архитектура с одним действием. Вместо того чтобы запускать новый Activity для каждого экрана, ваше приложение размещает один Activity и использует компонент Navigation для замены экранов, состоящих из функций, в рамках этого действия.

Чтобы узнать, как реализовать современную навигацию на основе Compose, ознакомьтесь с руководством по библиотеке Navigation 3 для Jetpack Compose.

Запуск одного действия из другого

В какой-то момент одному действию может потребоваться запустить другое. Например, это необходимо, когда приложение переходит с одного экрана на другой.

В зависимости от того, нужно ли вашему действию получить результат от нового действия, которое оно собирается запустить, вы можете использовать метод startActivity или startActivityForResult. В любом случае вы передаете объект Intent.

Объект Intent указывает на точное действие, которое нужно запустить, или описывает тип действия, которое нужно выполнить. Система выбирает подходящее действие, которое может быть даже из другого приложения. Объект Intent также может содержать небольшое количество данных, которые будут использоваться запущенным действием. Подробнее о классе Intent рассказывается в статье Намерения и фильтры намерений.

startActivity

Если новое действие не должно возвращать результат, текущее действие может запустить его, вызвав метод startActivity.

При работе с собственным приложением часто требуется просто запустить известное действие. Например, в приведенном ниже фрагменте кода показано, как запустить действие SignInActivity.

val context = LocalContext.current

Button(onClick = {
    val intent = Intent(context, SignInActivity::class.java)
    context.startActivity(intent)
}) {
    Text("Sign In")
}

Запуск внешних действий

Внутреннюю навигацию в приложении обрабатывает Navigation, но иногда Activity нужно запускать другие объекты activity. Обычно это происходит, когда вы хотите использовать внешнее приложение для выполнения определенного действия, например открыть веб-браузер, отправить электронное письмо или сделать фотографию.

Для этого используется объект Intent, в котором описывается тип действия, которое нужно выполнить. Система запускает подходящую операцию из другого приложения.

Например, если вы хотите разрешить пользователю отправлять электронные письма, создайте следующее намерение:

val intent = Intent(Intent.ACTION_SEND).apply {
    putExtra(Intent.EXTRA_EMAIL, recipientArray)
}
startActivity(intent)

Если вам нужно запустить внешнее действие и получить результат (например, попросить приложение камеры сделать фотографию и вернуть изображение), используйте современные Activity API результатов вместо устаревшего обратного вызова startActivityForResult.

Координация действий

Когда одно действие запускает другое, оба проходят через переход жизненного цикла. Первое действие останавливается и переходит в состояние "Приостановлено" или "Остановлено", а второе создается. Если эти действия обмениваются данными, сохраненными на диске или в другом месте, важно понимать, что первое действие не останавливается полностью до создания второго. Процесс запуска второго устройства будет происходить одновременно с процессом остановки первого.

Порядок обратных вызовов жизненного цикла хорошо определен, особенно когда два действия выполняются в одном процессе (то есть в одном приложении) и одно запускает другое. Ниже описана последовательность действий, которые происходят, когда Activity A запускает Activity B:

  1. Выполняется метод onPause класса Activity A.
  2. Методы onCreate, onStart и onResume класса Activity B выполняются последовательно. Теперь фокус пользователя находится на действии Б.
  3. Если Activity A больше не видно на экране, выполняется метод onStop.

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

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

Чтобы узнать больше о жизненном цикле объекта activity, ознакомьтесь со следующими дополнительными ресурсами:

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