Activity Lifecycle — скуп метода повратног позива које Android позива при преласку Activity између стања: креирање, видљивост, фокус уноса, делимични губитак видљивости, потпуно скривање и уништење. Систем управља животним циклусом сваког екрана апликације, почевши од тренутка позива onCreate() и завршавајући са onDestroy. Разумевање ових стања је обавезан захтев за стабилан рад Android апликације, јер неправилна обрада прелаза између метода доводи до цурења меморије, губитка података корисника и неочекиваних crash-ева. Више о архитектури Android-а прочитајте у општем чланку о Android-у.
Главно
Activity Lifecycle (животни циклус Activity) — коначни аутомат стања кроз који пролази сваки екран Android апликације од тренутка креирања до потпуног уништења. Систем Android управља овим процесом на основу радњи корисника: отварање апликације, минимизација, ротација екрана, одговор на долазни позив, прелазак између апликација и завршетак рада.
Разумевање животног циклуса је неопходно сваком Android програмеру, јер систем може у било ком тренутку уништити Activity при недостатку меморије — и апликација мора коректно да поврати своје стање. Према подацима Google Android Vitals (2025), апликације које не обрађују чување стања у onSaveInstanceState() показују 42% више crash-ева при поновном креирању 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 видљив; повезивање broadcast пријемника (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 и апликација ће пасти са crash-ем. Ово је строг захтев 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. године. Саветоваћемо вас и предложити најбоље решење.
Прочитајте такође