Activity Lifecycle — это набор методов обратного вызова, которые Android вызывает при переходе Activity между состояниями: создание, видимость, фокус ввода, частичная потеря видимости, полная скрытость и уничтожение. Система управляет жизненным циклом каждого экрана приложения, начиная с момента вызова onCreate() и заканчивая onDestroy(). Понимание этих состояний — обязательное требование для стабильной работы Android-приложения, поскольку неверная обработка перехода между методами приводит к утечкам памяти, потере данных пользователя и неожиданным крашам. Подробнее об архитектуре Android читайте в общей статье об Android.
Главное
Activity Lifecycle (жизненный цикл Activity) — это конечный автомат состояний, через который проходит каждый экран Android-приложения от момента создания до полного уничтожения. Система Android управляет этим процессом на основе действий пользователя: открытие приложения, сворачивание, поворот экрана, ответ на входящий звонок, переключение между приложениями и завершение работы.
Понимание жизненного цикла необходимо каждому Android-разработчику, поскольку система может в любой момент уничтожить Activity при нехватке памяти — и приложение обязано корректно восстановить своё состояние. Согласно данным Google Android Vitals (2025), приложения, не обрабатывающие сохранение состояния в onSaveInstanceState(), показывают на 42% больше крашей при пересоздании Activity.
Жизненный цикл включает шесть основных методов-колбэков: onCreate(), onStart(), onResume(), onPause(), onStop(), onDestroy(). Дополнительно существует метод onRestart(), который вызывается перед onStart(), когда Activity возвращается из остановленного состояния. Каждый метод имеет строго определённое назначение и время выполнения — система вызывает их последовательно, и разработчик может переопределить любой из них для выполнения своей логики.
Цикл можно разделить на три ключевых этапа: весь срок жизни (onCreate → onDestroy), видимый срок жизни (onStart → onStop) и срок жизни на переднем плане (onResume → onPause). Понимание этих трёх уровней помогает правильно распределить код инициализации и освобождения ресурсов.
Каждый метод жизненного цикла выполняет строго определённую задачу. Система вызывает их в фиксированном порядке, и разработчик должен переопределять только те методы, которые нужны для конкретной логики. Не рекомендуется вызывать методы жизненного цикла напрямую — этим занимается Android Runtime.
Типичная последовательность при запуске приложения: onCreate → onStart → onResume. При нажатии кнопки «Назад»: onPause → onStop → onDestroy. При сворачивании: onPause → onStop, затем при возврате: onRestart → onStart → onResume.
class MainActivity : AppCompatActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
}
override fun onStart() {
super.onStart()
}
override fun onResume() {
super.onResume()
}
override fun onPause() {
super.onPause()
}
override fun onStop() {
super.onStop()
}
override fun onDestroy() {
super.onDestroy()
}
override fun onRestart() {
super.onRestart()
}
}
Каждый переопределённый метод обязан вызывать super-версию — без этого система не сможет корректно завершить переход между состояниями. Это правило закреплено в документации Android Developers и проверяется lint-правилами Android Studio.
Первый уровень — весь срок жизни (entire lifetime): промежуток между onCreate и onDestroy. Здесь выполняется одноразовая инициализация и финальное освобождение глобальных ресурсов. Второй уровень — видимый срок жизни (visible lifetime): между onStart и onStop. Activity видна на экране, но может быть частично перекрыта другим окном. Третий уровень — срок жизни на переднем плане (foreground lifetime): между onResume и onPause. Activity находится на вершине стека задач и взаимодействует с пользователем.
onCreate() — первый и единственный обязательный метод жизненного цикла Activity. Он вызывается системой один раз при создании экземпляра Activity. Этот метод принимает параметр savedInstanceState: Bundle?, который содержит ранее сохранённое состояние, если Activity пересоздаётся после уничтожения — например, при повороте экрана.
Внутри onCreate выполняются следующие задачи: инициализация пользовательского интерфейса через setContentView() с передачей layout-ресурса, привязка View-элементов через findViewById(), настройка адаптеров для RecyclerView и ViewPager, восстановление состояния из savedInstanceState, инициализация ViewModel и LiveData, настройка слушателей кликов и жестов. Метод должен завершиться как можно быстрее — длительные операции здесь блокируют отрисовку первого кадра, что увеличивает время старта приложения.
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_profile)
val userNameText: TextView = findViewById(R.id.user_name)
val loadButton: Button = findViewById(R.id.load_button)
if (savedInstanceState != null) {
userNameText.text = savedInstanceState.getString("user_name")
}
loadButton.setOnClickListener {
loadUserProfile()
}
}
Если Activity создаётся впервые, savedInstanceState равен null. При пересоздании после поворота экрана Bundle содержит данные, сохранённые в onSaveInstanceState(). Проверка на null — стандартная практика для корректного восстановления UI без потери введённых пользователем данных.
onStart() вызывается сразу после onCreate() или после onRestart(), когда Activity становится видимой для пользователя. В этом состоянии Activity ещё не находится на переднем плане и не может взаимодействовать с пользователем, но её пользовательский интерфейс уже виден на экране. Например, при запуске приложения между вызовом onStart и onResume система отрисовывает первый кадр интерфейса.
В методе onStart обычно выполняются следующие действия: запуск анимаций, которые должны работать, пока Activity видна; привязка широковещательных приёмников (BroadcastReceiver); подключение к сервисам геолокации и датчикам; обновление данных из ViewModel или Room. Здесь же выполняют привязку к Bound-сервисам через bindService(), если приложение использует клиент-серверную архитектуру внутри процесса.
override fun onStart() {
super.onStart()
val locationManager = getSystemService(Context.LOCATION_SERVICE) as LocationManager
locationManager.requestLocationUpdates(
LocationManager.GPS_PROVIDER,
5000L,
10f,
locationListener
)
}
override fun onStop() {
super.onStop()
val locationManager = getSystemService(Context.LOCATION_SERVICE) as LocationManager
locationManager.removeUpdates(locationListener)
}
Важное правило: ресурсы, подключенные в onStart, должны освобождаться в onStop. Это гарантирует, что когда Activity не видна на экране, она не потребляет батарею и системные ресурсы. Google Play Store проверяет приложения на утечку LocationListener и других системных сервисов при модерации обновлений.
onResume() — состояние, в котором Activity находится на переднем плане и готова к взаимодействию с пользователем. Это рабочее состояние экрана: система передаёт Activity фокус ввода, и все события касания, клавиатурного ввода и жестов направляются этому экрану. Метод onResume вызывается каждый раз, когда Activity возвращается на передний план — после завершения другого Activity, после закрытия диалогового окна, после разблокировки устройства.
В onResume выполняют: возобновление анимаций, которые были приостановлены в onPause; открытие камеры и других эксклюзивных ресурсов; регистрацию сенсорных слушателей (акселерометр, гироскоп); запуск таймеров и секундомера для UI; обновление содержимого экрана актуальными данными. В паре onResume / onPause работают с ресурсами, которые должны быть активны только при фокусе — например, непрерывное распознавание речи или видеозахват.
override fun onResume() {
super.onResume()
cameraHolder.openCamera()
animator.resume()
sensorManager.registerListener(
stepCounter,
sensorManager.getDefaultSensor(Sensor.TYPE_STEP_COUNTER),
SensorManager.SENSOR_DELAY_NORMAL
)
}
override fun onPause() {
super.onPause()
cameraHolder.closeCamera()
animator.pause()
sensorManager.unregisterListener(stepCounter)
}
Разница между onStart и onResume существенна: Activity может быть видима (onStart), но не активна (onResume) — например, когда поверх неё отображается всплывающее диалоговое окно или прозрачный экран блокировки. Именно в onResume, а не в onStart, следует открывать эксклюзивные ресурсы, к которым нужен монопольный доступ.
onPause() вызывается, когда Activity теряет фокус ввода, но остаётся частично видимой. Типичные сценарии: открытие диалогового окна, нажатие кнопки «Недавние приложения», входящий звонок, нажатие кнопки «Домой» (в этом случае за onPause последует onStop). Метод onPause — последнее надёжное место для сохранения данных, которые пользователь не должен потерять.
В onPause выполняют: сохранение черновиков писем и форм ввода в Room или SharedPreferences; остановка анимаций и видеовоспроизведения; закрытие камеры и освобождение монопольных ресурсов; отмена дорогостоящих операций, не критичных для фона. Метод onPause должен завершаться за менее чем 100 миллисекунд — система блокирует переход к следующему Activity, пока onPause не вернёт управление, и превышение лимита приводит к ANR (Application Not Responding).
override fun onPause() {
super.onPause()
val editor = SharedPreferences.Manager ...
editor.putString("draft_text", draftEditText.text.toString())
editor.apply()
videoView.pause()
cameraHolder.release()
}
Важно: onPause выполняется в UI-потоке, поэтому любые блокирующие операции, такие как запись в базу данных через Room с синхронным запросом, должны быть заменены на асинхронные (корутины) или выполняться в фоновом потоке. Используйте apply() вместо commit() для SharedPreferences — apply записывает данные асинхронно и не блокирует UI-поток.
onStop() вызывается, когда Activity перестаёт быть видимой для пользователя. Это происходит в следующих случаях: Activity полностью перекрыто другим Activity; пользователь нажал кнопку «Домой» или переключился на другое приложение; Activity завершается (будет вызван затем onDestroy). В состоянии onStop Activity остаётся в памяти и сохраняет все свои поля — оно не уничтожено, но и не активно.
В onStop выполняют: отписку от BroadcastReceiver, зарегистрированных в onStart; отключение от Bound-сервисов; освобждение LocationListener, SensorListener и других системных слушателей; остановку длительных фоновых операций, которые не нужны, когда приложение скрыто; запись текущего состояния UI в Bundle через onSaveInstanceState(), если это не было сделано в onPause.
override fun onStop() {
super.onStop()
unregisterReceiver(connectivityReceiver)
unbindService(serviceConnection)
if (isChangingConfigurations()) {
Log.d("Lifecycle", "Activity пересоздаётся из-за конфигурации")
}
}
Система может уничтожить Activity в состоянии onStop без вызова onDestroy при нехватке памяти. Поэтому все критичные данные должны быть сохранены до перехода в onStop. Флаг isChangingConfigurations() позволяет определить, связан ли вызов onStop с поворотом экрана — в этом случае Activity будет пересоздано, а не завершено.
onDestroy() — последний метод жизненного цикла, вызываемый перед полным уничтожением Activity. Система вызывает onDestroy в двух случаях: Activity завершается вызовом finish() или пользователь нажимает кнопку «Назад»; Activity уничтожается системой из-за изменения конфигурации (например, поворот экрана) и будет создано заново. Метод onDestroy позволяет выполнить финальную очистку ресурсов: отвязку потоков и корутин, закрытие permanently открытых курсоров и сокетов, освобождение нативной памяти через NDK.
override fun onDestroy() {
super.onDestroy()
backgroundJob.cancel()
dbHelper.close()
if (isFinishing) {
Log.d("Lifecycle", "Activity завершается окончательно")
} else {
Log.d("Lifecycle", "Activity будет пересоздано")
}
}
Важное замечание: в onDestroy не гарантируется вызов, если процесс приложения убит системой (out-of-memory kill). Поэтому полагаться на onDestroy для сохранения данных нельзя — эта задача решается в onPause или onStop. Свойство isFinishing позволяет отличить завершение Activity по finish() от пересоздания при изменении конфигурации.
onRestart() вызывается перед onStart(), когда Activity возвращается из остановленного состояния (onStop) обратно на передний план. Это происходит, когда пользователь повторно открывает приложение из меню «Недавние» или возвращается к Activity, нажав «Назад» в дочернем экране. Метод onRestart позволяет выполнить логику, отличную от onCreate, — например, обновить данные, которые могли измениться, пока Activity было скрыто.
override fun onRestart() {
super.onRestart()
refreshDataFromNetwork()
Log.d("Lifecycle", "Activity перезапускается из стека")
}
Типичный сценарий: пользователь открыл приложение, переключился на другую задачу, а через час вернулся. В onRestart приложение может проверить актуальность данных и, если прошло много времени, предложить перезагрузить контент. Это улучшает пользовательский опыт и снижает вероятность показа устаревшей информации.
Поворот экрана — самый частый сценарий пересоздания Activity. По умолчанию Android уничтожает текущую Activity и создаёт новую при каждом изменении ориентации. Если не сохранить состояние, пользователь потеряет все введённые данные. Для этого Android предоставляет два механизма: onSaveInstanceState() для сериализуемых данных и ViewModel для данных, переживающих конфигурационные изменения.
onSaveInstanceState() вызывается перед уничтожением Activity для сохранения временного состояния. Сохранённые данные передаются в onCreate через параметр savedInstanceState и в метод onRestoreInstanceState(), который вызывается после onStart. Bundle имеет ограничение по размеру — около 500 КБ, поэтому большие объёмы данных (например, битмапы) сохраняют через ViewModel.
<!-- AndroidManifest.xml — фиксация ориентации -->
<activity android:name=".MainActivity"
android:configChanges="orientation|screenSize" />
Фиксация ориентации через android:configChanges предотвращает пересоздание Activity, но считается антипаттерном, если приложение должно поддерживать обе ориентации. Современная рекомендация Google — использовать ViewModel в связке с onSaveInstanceState для данных, которые пользователь вводит в UI.
Fragment имеет собственный жизненный цикл, похожий на Activity, но с дополнительными методами: onAttach, onCreate, onCreateView, onViewCreated, onStart, onResume, onPause, onStop, onDestroyView, onDestroy, onDetach. Fragment всегда существует внутри Activity, и его жизненный цикл привязан к жизненному циклу Activity-контейнера. Если Activity уничтожается, Fragment следует за ним.
Основное отличие: Fragment управляет не только состоянием компонента, но и иерархией View. Метод onCreateView возвращает корневой View фрагмента, а onDestroyView — уничтожает эту иерархию. Это позволяет Fragment переживать пересоздание Activity при повороте экрана: Fragment сохраняется, а его View создаётся заново в onCreateView.
class ProfileFragment : Fragment() {
override fun onCreateView(
inflater: LayoutInflater,
container: ViewGroup?,
savedInstanceState: Bundle?
): View {
return inflater.inflate(R.layout.fragment_profile, container, false)
}
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
super.onViewCreated(view, savedInstanceState)
val avatarImage: ImageView = view.findViewById(R.id.avatar_image)
loadAvatar(avatarImage)
}
}
Понимание разницы между onCreate и onCreateView критически важно: onCreate вызывается один раз за жизнь Fragment (даже при пересоздании View), а onCreateView — каждый раз, когда Fragment создаёт или пересоздаёт свою иерархию View. Инициализацию данных выполняют в onCreate, а привязку UI — в onViewCreated.
LifecycleObserver — компонент библиотеки Android Jetpack, который позволяет реагировать на изменения жизненного цикла без переопределения методов в Activity или Fragment. Вместо того чтобы дублировать код в каждом методе жизненного цикла, разработчик создаёт отдельный класс с аннотациями @OnLifecycleEvent и передаёт его в lifecycle.addObserver().
Jetpack также предоставляет класс LifecycleOwner — интерфейс, который реализуют AppCompatActivity и Fragment. Любой объект, реализующий LifecycleOwner, может управлять подписками LiveData, корутин через lifecycleScope и работу WorkManager в привязке к жизненному циклу. Это краеугольный камень современной архитектуры Android, основанной на MVVM и Jetpack.
class MyLocationObserver(private val context: Context) : DefaultLifecycleObserver {
override fun onStart(owner: LifecycleOwner) {
startLocationUpdates()
}
override fun onStop(owner: LifecycleOwner) {
stopLocationUpdates()
}
}
// В Activity:
lifecycle.addObserver(MyLocationObserver(this))
Использование DefaultLifecycleObserver упрощает тестирование, уменьшает дублирование кода и делает логику жизненного цикла переиспользуемой между разными экранами. Это современная замена ручному переопределению onStart/onStop в каждом Activity. В Android-приложениях, разработанных IT Sectr, мы применяем LifecycleObserver для геолокации, Bluetooth-сканирования и аналитики — это сокращает объём boilerplate-кода на 30–40%.
Часто задаваемые вопросы
Если не вызвать super.onCreate() или любой другой super-метод жизненного цикла, система выбросит исключение SuperNotCalledException и приложение упадёт с крашем. Это жёсткое требование Android Runtime — каждый метод обязан делегировать выполнение базовому классу, иначе внутренний конечный автомат не сможет перейти в следующее состояние.
Activity пересоздаётся при повороте экрана, потому что изменение ориентации — это изменение конфигурации устройства (configuration change). По умолчанию Android уничтожает Activity и создаёт новую, чтобы загрузить альтернативные ресурсы (layout-land, values-land). Чтобы отключить пересоздание, можно добавить атрибут android:configChanges в манифест, но Google рекомендует использовать ViewModel для сохранения данных.
Критичные данные сохраняют в onPause(), так как это последний метод, который гарантированно вызывается перед тем, как приложение может быть убито системой. После onStop и onDestroy система может завершить процесс без вызова дополнительных методов. Для черновиков и промежуточных данных используйте SharedPreferences с apply() или Room с корутинами.
onPause вызывается, когда Activity теряет фокус, но остаётся частично видимой (например, открыто диалоговое окно). onStop вызывается, когда Activity полностью скрыта с экрана другим Activity или нажатием кнопки «Домой». Основное практическое различие: onPause — последняя точка сохранения данных, onStop — место освобождения слушателей и системных сервисов, которые не нужны в фоне.
ViewModel — компонент Android Jetpack, который хранит данные UI и автоматически переживает конфигурационные изменения (поворот экрана). ViewModel не уничтожается при пересоздании Activity: она живёт, пока LifecycleOwner (Activity или Fragment) не завершится окончательно. Это решает проблему сохранения данных при повороте экрана без использования Bundle и onSaveInstanceState. ViewModel — обязательный элемент архитектуры MVVM, рекомендованной Google.
Итоги
Мы разработаем мобильное приложение под ключ
IT Sectr создаёт приложения для iOS и Android для стартапов и бизнеса с 2017 года. Мы проконсультируем вас и предложим наилучшее решение.
Читайте также