Когда пользователь переходит между экранами приложения, сворачивает и разворачивает его, экземпляры Activity в приложении переходят из одного состояния жизненного цикла в другое.
Класс Activity предоставляет ряд обратных вызовов, которые позволяют операции узнать, когда изменяется состояние или когда система создает, останавливает или возобновляет операцию или уничтожает процесс, в котором находится операция.
В методах обратного вызова жизненного цикла можно объявить, как будет вести себя действие, когда пользователь покидает его и возвращается. Например, если вы создаете видеопроигрыватель, то можете приостанавливать воспроизведение и отключаться от сети, когда пользователь переключается на другое приложение. Когда он вернется, вы сможете снова подключиться к сети и возобновить воспроизведение с того же места.
Каждый обратный вызов позволяет выполнять определенную работу, соответствующую данному изменению состояния. Выполнение правильной работы в нужное время и правильная обработка переходов делают ваше приложение более надежным и производительным. Например, правильная реализация обратных вызовов жизненного цикла может помочь вашему приложению избежать следующего:
- Приложение аварийно завершает работу, когда пользователь принимает звонок или переключается на другое приложение.
- Потребление ценных системных ресурсов, когда пользователь не работает с приложением.
- Потеря прогресса пользователя, если он покинет приложение и вернется в него позже.
- Сбои или потеря прогресса пользователя при повороте экрана между альбомной и портретной ориентацией.
В этом документе подробно описан жизненный цикл объекта activity. Документ начинается с описания парадигмы жизненного цикла. Затем мы рассмотрим каждый из обратных вызовов: что происходит внутри во время их выполнения и что вам нужно реализовать во время них.
Затем кратко описывается связь между состоянием действия и уязвимостью процесса к завершению системой. Наконец, в ней рассматривается несколько тем, связанных с переходами между состояниями активности.
Информацию о работе с жизненными циклами, включая рекомендации, можно найти в статьях Жизненный цикл в Jetpack Compose и Сохранение состояний пользовательского интерфейса. Чтобы узнать, как создать надежное приложение производственного качества, используя действия в сочетании с компонентами архитектуры, ознакомьтесь с Руководством по архитектуре приложений.
Концепции жизненного цикла объекта activity
Для навигации по переходам между этапами жизненного цикла объекта activity класс Activity предоставляет основной набор из шести обратных вызовов: onCreate, onStart, onResume, onPause, onStop и onDestroy. Система вызывает каждый из этих обратных вызовов, когда действие переходит в новое состояние.
На рисунке 1 показано визуальное представление этой парадигмы.
Когда пользователь начинает покидать объект activity, система вызывает методы для его демонтажа. В некоторых случаях действие демонтируется лишь частично и по-прежнему находится в памяти, например когда пользователь переключается на другое приложение. В таких случаях действие все равно может вернуться на передний план.
Если пользователь возвращается к действию, оно возобновляется с того места, где было прервано. За некоторыми исключениями, приложениям запрещено запускать действия в фоновом режиме.
Вероятность того, что система завершит определенный процесс и все связанные с ним действия, зависит от состояния действия в данный момент. Дополнительную информацию о связи между состоянием и уязвимостью к вытеснению можно найти в разделе Состояние активности и вытеснение из памяти.
В зависимости от сложности действия вам, скорее всего, не потребуется реализовывать все методы жизненного цикла. Однако важно понимать, как работает каждый из них, и использовать те, которые обеспечивают ожидаемое поведение приложения.
Compose и жизненный цикл
В Compose не размещайте бизнес-логику или ручную настройку наблюдателя непосредственно в обратных вызовах активности, таких как onStart или onResume. Вместо этого используйте эффекты, учитывающие жизненный цикл, и наблюдатели, учитывающие состояние, которые автоматически выравниваются по наличию пользовательского интерфейса на экране.
- Сбор данных с учетом жизненного цикла. Используйте
collectAsStateWithLifecycle, чтобы получать потоки изViewModel. Этот API автоматически начинает сбор данных, когда интерфейс переходит в состояние Started, и останавливает его, когда интерфейс переходит в фоновый режим, что предотвращает ненужное потребление ресурсов. После сбора потока в виде состояния вы можете использоватьLifecycleEffectsдля запуска кода при возникновении события жизненного цикла. - Логика. С помощью этих API интерфейс реагирует на состояние жизненного цикла естественным образом через дерево композиции, гарантируя, что бизнес-логика выполняется только тогда, когда пользователь активно взаимодействует с компонентом.
Подробнее о жизненном цикле в Jetpack Compose…
Обратные вызовы жизненного цикла
В этом разделе приведены концептуальные сведения и информация о реализации методов обратного вызова, используемых в течение жизненного цикла объекта activity.
Некоторые действия относятся к методам жизненного цикла объекта activity. Однако код, реализующий действия зависимого компонента, следует размещать в самом компоненте, а не в методе жизненного цикла объекта activity. Для этого нужно сделать зависимый компонент осведомленным о жизненном цикле. Чтобы узнать, как сделать зависимые компоненты учитывающими жизненный цикл, ознакомьтесь со статьей Жизненный цикл в Jetpack Compose.
onCreate
Вы должны реализовать этот обратный вызов, который срабатывает, когда система впервые создает действие. После создания действие получает статус Создано. В методе onCreate реализуйте базовую логику запуска приложения, которая выполняется только один раз за весь жизненный цикл операции.
Например, ваша реализация onCreate может связывать данные со списками, ассоциировать действие с ViewModel и создавать экземпляры некоторых переменных в области видимости класса. Этот метод получает параметр savedInstanceState, который является объектом Bundle, содержащим ранее сохраненное состояние операции. Если действие никогда не существовало, значение объекта Bundle будет равно null.
Если у вас есть компонент, учитывающий жизненный цикл, который подключен к жизненному циклу вашего действия, он получает событие ON_CREATE. Вызывается метод, аннотированный с помощью @OnLifecycleEvent, чтобы компонент, учитывающий жизненный цикл, мог выполнить любой код настройки, необходимый для созданного состояния.
В примере ниже показано, как интегрировать 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 переходит в состояние Started, любой компонент, связанный с его жизненным циклом, получает событие ON_START.
Метод onStart выполняется быстро, и, как и в случае с состоянием Created, действие не остается в состоянии Started. После завершения этого обратного вызова объект activity переходит в состояние Resumed, и система вызывает метод onResume.
onResume
Когда объект activity переходит в состояние Resumed, он выходит на передний план и система вызывает обратный вызов onResume. Это состояние, в котором приложение
взаимодействует с пользователем. Приложение остается в этом состоянии, пока не произойдет событие, которое отвлечет внимание от приложения, например устройство получит телефонный звонок, пользователь перейдет к другому действию или экран устройства выключится.
Когда действие переходит в состояние Resumed, любой компонент, связанный с жизненным циклом действия, получает событие ON_RESUME. Здесь компоненты жизненного цикла могут включать любые функции, которые должны работать, пока компонент виден и находится на переднем плане, например запуск предварительного просмотра камеры.
Когда происходит прерывание, действие переходит в состояние Приостановлено, а система вызывает обратный вызов onPause.
Если объект activity возвращается в состояние Resumed из состояния Paused, система снова вызывает метод onResume. Поэтому реализуйте onResume, чтобы инициализировать компоненты, которые вы выпускаете во время onPause, и выполнять любые другие инициализации, которые должны происходить каждый раз, когда действие переходит в состояние Resumed.
Ниже приведен пример компонента с учетом жизненного цикла, который обращается к камере, когда компонент получает событие ON_RESUME:
class CameraComponent : LifecycleObserver {
...
@OnLifecycleEvent(Lifecycle.Event.ON_RESUME)
fun initializeCamera() {
if (camera == null) {
getCamera()
}
}
...
}
Приведенный выше код инициализирует камеру, как только LifecycleObserver получает событие ON_RESUME. Однако в многооконном режиме ваше действие может быть полностью видимым, даже если оно находится в состоянии Paused. Например, если приложение находится в многооконном режиме и пользователь нажимает на окно, которое не содержит вашу активность, она переходит в состояние Paused.
Если вы хотите, чтобы камера была активна, только когда приложение возобновлено (видимо и активно на переднем плане), инициализируйте камеру после события ON_RESUME, как показано выше. Если вы хотите, чтобы камера оставалась активной, когда действие приостановлено, но видно, например в многооконном режиме, инициализируйте камеру после события ON_START.
Однако если камера будет активна, когда действие приостановлено, другое возобновленное приложение в многооконном режиме может не получить доступ к камере. Иногда необходимо, чтобы камера оставалась активной, когда действие приостановлено, но это может ухудшить общее впечатление пользователя.
Поэтому тщательно продумайте, на каком этапе жизненного цикла лучше всего брать под контроль общие системные ресурсы в контексте многооконного режима. Подробнее о том, как реализовать поддержку многооконного режима…
Независимо от того, какое событие вы выберете для инициализации, обязательно используйте соответствующее событие жизненного цикла, чтобы освободить ресурс. Если вы инициализируете что-то после события ON_START, освободите или завершите это после события ON_STOP. Если инициализация выполняется после события ON_RESUME, то освобождение должно выполняться после события ON_PAUSE.
Приведенный выше фрагмент кода помещает код инициализации камеры в компонент, учитывающий жизненный цикл. Вы можете поместить этот код непосредственно в обратные вызовы жизненного цикла объекта activity, например onStart и onStop, но мы не рекомендуем этого делать. Добавление этой логики в независимый компонент, учитывающий жизненный цикл, позволяет повторно использовать компонент в нескольких действиях без дублирования кода. Чтобы узнать, как создать компонент, учитывающий жизненный цикл, ознакомьтесь со статьей Жизненный цикл в Jetpack Compose.
onPause
Система вызывает этот метод, когда пользователь покидает операцию. Это не всегда означает, что операция будет уничтожена. Это означает, что действие больше не выполняется в активном режиме, но по-прежнему видно, если пользователь находится в многооконном режиме. Это может произойти по нескольким причинам:
- Событие, которое прерывает выполнение приложения, как описано в разделе об обратном вызове
onResume, приостанавливает текущее действие. Это самый распространенный случай. - В многооконном режиме в каждый момент времени только одно приложение находится в фокусе, а все остальные приостановлены.
- Открытие нового полупрозрачного действия, например диалогового окна, приостанавливает действие, которое оно перекрывает. Пока активность частично видна, но не в фокусе, она остается приостановленной.
Когда действие переходит в состояние Paused, любой компонент, связанный с его жизненным циклом, получает событие ON_PAUSE. Здесь компоненты жизненного цикла могут остановить любую функциональность, которая не должна работать, пока компонент не находится на переднем плане, например, остановить предварительный просмотр камеры.
Используйте метод onPause, чтобы приостановить или скорректировать операции, которые не могут продолжаться или могут продолжаться в ограниченном режиме, пока Activity находится в состоянии Paused, и которые вы планируете возобновить в ближайшее время.
Метод 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 не означает, что операция выходит из состояния приостановки. Вместо этого действие остается в этом состоянии до тех пор, пока оно не возобновится или не станет полностью невидимым для пользователя. Если операция возобновляется, система снова вызывает обратный вызов onResume.
Если объект activity возвращается из состояния Paused в состояние Resumed, система сохраняет экземпляр Activity в памяти и вызывает его при вызове onResume. В этом случае вам не нужно повторно инициализировать компоненты, созданные во время выполнения методов обратного вызова, которые предшествуют состоянию Resumed. Если объект activity становится полностью невидимым, система вызывает метод onStop.
onStop
Когда операция больше не видна пользователю, она переходит в состояние Остановлено, и система вызывает обратный вызов 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 остается в памяти. Он сохраняет все сведения о состоянии и элементах, но не прикреплен к диспетчеру окон. Когда активность возобновляется, она вспоминает эту информацию.
Из состояния Stopped активность либо возвращается к взаимодействию с пользователем, либо завершает работу и исчезает. Если объект activity возвращается, система вызывает метод onRestart. Если выполнение Activity завершено, система вызывает onDestroy.
onDestroy
onDestroy вызывается перед удалением действия. Система вызывает этот обратный вызов по одной из двух причин:
- Действие завершается, поскольку пользователь полностью закрыл его или в действии был вызван метод
finish. - Система временно уничтожает действие из-за изменения конфигурации, например поворота устройства или перехода в многооконный режим.
Когда действие переходит в состояние уничтожения, любой компонент, связанный с жизненным циклом действия, получает событие ON_DESTROY. В этот момент компоненты жизненного цикла могут выполнить необходимые действия по очистке перед удалением Activity.
Вместо того чтобы добавлять в Activity логику, определяющую причину уничтожения, используйте объект ViewModel, который будет содержать данные представления, относящиеся к Activity. Если Activity создается заново из-за изменения конфигурации, ViewModel не нужно ничего делать, так как он сохраняется и передается следующему экземпляру Activity.
Если Activity не создается заново, то для ViewModel вызывается метод onCleared, который позволяет очистить все необходимые данные перед удалением. Различить эти два сценария можно с помощью метода isFinishing.
Если действие завершается, onDestroy – это последний обратный вызов жизненного цикла, который получает действие. Если метод onDestroy вызывается в результате изменения конфигурации, система немедленно создает новый экземпляр действия, а затем вызывает метод onCreate для этого нового экземпляра в новой конфигурации.
Обратный вызов onDestroy освобождает все ресурсы, которые не были освобождены предыдущими обратными вызовами, например onStop.
Состояние действия и удаление из памяти
Система завершает процессы, когда ей нужно освободить ОЗУ. Вероятность того, что система завершит определенный процесс, зависит от его состояния в данный момент. Состояние процесса, в свою очередь, зависит от состояния действия, выполняемого в процессе. В таблице 1 показаны корреляции между состоянием процесса, состоянием действия и вероятностью того, что система завершит процесс. Эта таблица применяется, только если процесс не выполняет другие типы компонентов приложения.
Вероятность быть убитым |
Состояние процесса |
Конечное состояние действия |
Самый низкий |
Активное (в фокусе или скоро будет в фокусе) |
Возобновление |
Низкий |
Видно (не в фокусе) |
Запущено/приостановлено |
Более высокое |
Фон (невидимый) |
Остановлено |
Самый высокий |
Пусто |
Удалено |
Таблица 1. Связь между жизненным циклом процесса и состоянием действия.
Система никогда не завершает действия напрямую, чтобы освободить память. Вместо этого она завершает процесс, в котором выполняется действие, уничтожая не только действие, но и все остальное, что выполняется в этом процессе. Чтобы узнать, как сохранить и восстановить состояние интерфейса операции при завершении процесса, инициированном системой, прочитайте раздел Сохранение и восстановление состояния.
Пользователь также может завершить процесс, закрыв соответствующее приложение в Диспетчере приложений в разделе "Настройки".
Подробнее о процессах и потоках…
Сохранение и восстановление временного состояния пользовательского интерфейса
Пользователь ожидает, что состояние интерфейса действия останется неизменным при изменении конфигурации, например при повороте экрана или переключении в многооконный режим. Однако по умолчанию система уничтожает операцию при изменении конфигурации, стирая любое состояние пользовательского интерфейса, сохраненное в экземпляре операции.
Аналогично, пользователь ожидает, что состояние пользовательского интерфейса останется прежним, если он временно переключится из вашего приложения в другое, а затем вернется в ваше приложение позже. Однако система может уничтожить процесс вашего приложения, пока пользователь отсутствует и ваша активность остановлена.
Если системные ограничения приводят к уничтожению действия, сохраните временное состояние пользовательского интерфейса, используя ViewModel (для сложной бизнес-логики и состояния экрана), API Jetpack Compose rememberSaveable (для простого состояния пользовательского интерфейса) и/или локальное хранилище. Чтобы узнать больше об ожиданиях пользователей в сравнении с поведением системы и о том, как лучше всего сохранять сложные данные о состоянии пользовательского интерфейса при инициированных системой действиях и завершении процесса, ознакомьтесь со статьей Сохранение состояний пользовательского интерфейса.
rememberSaveable автоматически сохраняет состояние при изменении конфигурации и завершении процесса системой, объединяя состояние под капотом и обеспечивая бесперебойную работу без необходимости в шаблонном коде на уровне действия.
Состояние экземпляра
Есть несколько сценариев, в которых действие уничтожается в результате нормального поведения приложения, например когда пользователь нажимает кнопку "Назад" или действие сигнализирует о собственном уничтожении, вызывая метод finish.
Когда операция уничтожается, потому что пользователь нажимает кнопку "Назад" или операция завершается сама, экземпляр Activity удаляется навсегда. В таких случаях ожидания пользователя совпадают с поведением системы, и вам не нужно ничего делать.
Однако если система уничтожает действие из-за системных ограничений (например, изменения конфигурации или нехватки памяти), то, хотя фактический экземпляр Activity исчез, система помнит, что он существовал. Если пользователь попытается вернуться к действию, система создаст его новый экземпляр, используя набор сохраненных данных, описывающих состояние действия на момент его уничтожения.
Сохраненные данные, которые система использует для восстановления предыдущего состояния, называются состоянием экземпляра. По сути, это набор пар "ключ-значение". По умолчанию система использует состояние экземпляра для сохранения базовой информации о макете пользовательского интерфейса, например введенного пользователем текста или положения прокрутки.
Для этого используется метод rememberSaveable. Если экземпляр действия будет удален и создан заново, любое состояние интерфейса, обернутое в rememberSaveable, будет автоматически восстановлено без необходимости писать дополнительный код на уровне действия.
Однако в вашем действии, скорее всего, будет более сложная информация о состоянии, которую вы захотите восстановить, например пользовательские данные, сетевые ответы или переменные-члены, отслеживающие прогресс пользователя. Механизм состояния экземпляра (и, как следствие, rememberSaveable) не подходит для сохранения большого объема данных, поскольку требует сериализации в основном потоке и потребляет память системного процесса.
Чтобы сохранить больше данных, используйте комбинированный подход с постоянным локальным хранилищем, классом ViewModel и передачей состояния Compose, как описано в статье Сохранение состояний пользовательского интерфейса.
Как сохранять простое и легковесное состояние пользовательского интерфейса с помощью rememberSaveable
Когда действие начинает останавливаться, система готовится сохранить информацию о состоянии в пакете состояния экземпляра. Чтобы подключиться к этому системному поведению, используйте rememberSaveable непосредственно в composable-функциях.
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 для переключения между composable-экранами в рамках этой activity.
Чтобы узнать, как реализовать современную навигацию, ориентированную на 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 иногда потребуется запускать другие действия. Обычно это происходит, когда вы хотите использовать внешнее приложение для выполнения определенного действия, например открытия веб-браузера, отправки электронного письма или фотосъемки.
Для этого вы используете объект Intent, чтобы описать тип действия, которое хотите выполнить, и система запускает соответствующее действие из другого приложения.
Например, если вы хотите, чтобы пользователь мог отправить электронное письмо, вы можете создать следующее намерение:
val intent = Intent(Intent.ACTION_SEND).apply {
putExtra(Intent.EXTRA_EMAIL, recipientArray)
}
startActivity(intent)
Если вам нужно запустить внешнее действие и получить результат (например, попросить приложение камеры сделать снимок и вернуть изображение), используйте современные API результатов Activity, а не устаревший обратный вызов startActivityForResult.
Координация действий
Когда одно действие запускает другое, они оба проходят через переходы жизненного цикла. Первое действие прекращает работу и переходит в состояние Paused или Stopped, а второе действие создается. Если эти действия используют общие данные, сохраненные на диске или в другом месте, важно понимать, что первое действие не будет полностью остановлено до создания второго. Процесс запуска второго перекрывается с процессом остановки первого.
Порядок обратных вызовов жизненного цикла четко определен, особенно когда два действия находятся в одном процессе (то есть в одном приложении) и одно действие запускает другое. Ниже описан порядок операций, которые выполняются, когда Activity А запускает Activity Б.
- Выполняется метод
onPauseдействия А. - Последовательно выполняются методы
onCreate,onStartиonResumeActivity B. Теперь пользователь видит действие Б. - Если действие А больше не видно на экране, выполняется его метод
onStop.
Эта последовательность обратных вызовов жизненного цикла позволяет управлять переходом информации от одного действия к другому.
Дополнительные ресурсы
Дополнительную информацию о жизненном цикле объекта activity вы можете найти в следующих ресурсах: