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 позволява окончателно почистване на ресурси: прекъсване на нишки и корутини, затваряне на постоянно отворени курсори и сокети, освобождаване на родна памет чрез 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 KB, следователно големи обеми данни (например битмапи) се запазват чрез 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 г. Ще ви консултираме и ще предложим най-доброто решение.
Прочетете също