onStop — шта је то, скривање Activity у животном циклусу Android-а

Аутор: IT Sectr Објављено: 2026-03-04 Време читања: 9 мин

onStop — метод животног циклуса Activity у Android-у, који позива систем када Activity престане да буде видљива кориснику. Activity прелази у стање Stopped након што је нова Activity потпуно прекрије или приликом минимизирања апликације. У методи onStop програмер је дужан да заустави анимације, ослободи ресурсе камере и сензора, сачува нацрте унетих података. Према Android Vitals (Google, 2025), коректна обрада onStop смањује број ANR (Application Not Responding) при минимизирању апликације за 35%. Након onStop систем може позвати onRestart (повратак на екран) или onDestroy (потпуни завршетак). Документација Android Developers о животном циклусу Activity описује onStop као границу између видљивог и невидљивог стања.

Главне тачке

  • onStop — метод који се позива при потпуном губитку видљивости Activity, али Activity се још увек налази у меморији.
  • Након onStop Activity прелази у стање Stopped — жива је у меморији, али није видљива и не интерагује са корисником.
  • Систем може позвати onRestart → onStart → onResume при повратку на Activity или onDestroy при завршетку.
  • У onStop је потребно ослободити ресурсе: зауставити анимације, искључити сензоре и камеру, сачувати привремене податке.
  • Коректна имплементација onStop — кључни фактор стабилности апликације при мултитаскингу и минимизирању.

Шта је onStop у Android-у?

onStop — је callback метода класе AppCompatActivity (и њеног претходника Activity), коју позива оперативни систем Android када Activity престане да буде потпуно видљива кориснику. У том тренутку Activity је скривена другим Activity, дијалог прозором, системским ланчером или екраном закључавања. Са становишта животног циклуса, onStop следи након onPause и сигнализира да Activity више није видљива на екрану, иако сам објекат Activity и његово стање остају у меморији.

Када Activity пређе у стање Stopped (заустављено), она задржава своје стање у RAM меморији — сва поља, View хијерархија и ViewModel остају доступни. Ово разликује Stopped од уништеног (Destroyed) стања, где се Activity потпуно уклања. System UI може убити процес апликације која се налази у стању Stopped при недостатку меморије — то је такозвани process death. Програмер је дужан да сачува критичне податке (нацрте, позицију скроловања) у onSaveInstanceState(), који се позива пре onStop, како би гарантовао опоравак при убијању процеса.

Према спецификацији Android Compatibility Definition Document (CDD) за верзију 14+, процес у стању Stopped има нижи приоритет при убијању од стране OOM Killer-а — нижи од процеса у фази Background, али виши од кешираних процеса. Према Google статистици, 68% случајева убијања процеса дешава се када је Activity у стању Stopped, а не Paused.

Када се позива onStop: сценарији и редослед

onStop се позива при потпуном губитку видљивости Activity, без обзира на узрок: покретање нове Activity изнад тренутне, минимизирање апликације (притиском Home), закључавање екрана, долазни позив или отварање системског дијалога. У свим овим случајевима Activity прво добија onPause (делимични губитак фокуса), а затим onStop (потпуни губитак видљивости).

Основни сценарији позивања onStop:

  • Покретање нове Activity изнад тренутне — тренутна Activity добија onPause, затим onStop; нова Activity пролази onCreate → onStart → onResume.
  • Минимизирање апликације (Home) — Activity прелази у onPause → onStop за 200–300 ms, остаје у меморији у стању Stopped.
  • Закључавање екрана — систем позива onPause → onStop, јер екран закључавања потпуно прекрива Activity.
  • Долазни позив — Activity телефона (Dialer) се покреће изнад, тренутна Activity прелази у onStop.
  • Прелазак на другу апликацију (Recent Apps) — Activity се скрива, добија onStop, али остаје у кешу процеса.

Важно је разумети да се onStop не позива при ротацији екрана — у овом случају Activity се уништава (onPause → onStop → onDestroy) и поново креира (onCreate → onStart → onResume). Изузетак — флаг android:configChanges="orientation" у манифесту, при којем се Activity не рекреира, већ добија позив onConfigurationChanged().

onStop у животном циклусу Activity

onStop заузима централно место у секвенци животног циклуса Activity између видљивог и невидљивог стања. Потпуна секвенца: onCreate → onStart → onResume → (активно стање) → onPause → onStop → onDestroy (или onRestart → onStart → onResume при повратку).

СтањеМетодВидљивостИнтеракцијаМеморија
CreatedonCreateНеНеАлоцирана
StartedonStartДелимичноНеПуна
ResumedonResumeПунаДаПуна
PausedonPauseДелимичноНеПуна
StoppedonStopНеНеПуна*
DestroyedonDestroyНеНеОслобођена

*У стању Stopped Activity се чува у меморији, али може бити убијена од стране система при недостатку ресурса. Приоритет убијања Stopped процеса — претпоследњи, виши само од празних кешираних процеса.

onStop и onSaveInstanceState: Систем позива onSaveInstanceState(Bundle) пре onStop за чување динамичког стања UI. Програмер преоптерећује овај метод да сачува у Bundle вредности поља за унос, позицију RecyclerView, изабране елементе. Чак и ако Activity не буде уништена (корисник је једноставно минимизирао и вратио се), Bundle се прослеђује у onCreate при конфигурационим променама. Google препоручује чување само пролазног UI стања — не података репозиторијума или ViewModel-а, који живе ван Activity.

Које ресурсе ослободити у onStop

У onStop програмер је дужан да ослободи све ресурсе који нису потребни када Activity није видљива. То смањује оптерећење батерије, процесора и меморије, а такође спречава ANR при повратку на активност.

Шта ослободити у onStop:

  • Анимације и transitions — зауставити ObjectAnimator, ValueAnimator, ViewPropertyAnimator. Анимација невидљиве Activity која ради је губљење GPU циклуса.
  • Сензори (Sensors) — одјавити се са SensorManager-а (акцелерометар, жироскоп, магнетометар). Сензори троше енергију чак и када је Activity скривена.
  • Камера и микрофон — ослободити Camera2 или CameraX, зауставити MediaRecorder. Остављање камере активне при скривеној Activity забрањено је Google Play политиком.
  • LocationListener — одјавити се са FusedLocationProviderClient-а или LocationManager-а. Геолокација је најенергетски захтевнији ресурс.
  • Network listeners — затворити WebSocket, отказати HTTP захтеве који нису потребни у позадини.
  • MediaPlayer и ExoPlayer — ставити на паузу или зауставити, ако репродукција не треба да се настави у позадини.

Шта не радити у onStop: Не обављајте дуготрајне операције — чување великих података у бази, мрежне захтеве, сложена израчунавања. onStop се извршава на главној нити и блокира повратак на Activity. За дуготрајне операције користите WorkManager са кашњењем или корутине у viewModelScope. Немојте ослобађати ViewModel ресурсе — ViewModel преживљава onStop и биће коришћен при повратку.

Разлика између onStop и onPause

onPause и onStop се разликују по степену губитка видљивости и обиму обавезних радњи. onPause се позива при делимичном губитку фокуса (на пример, отварање дијалог прозора или системског менија), onStop — при потпуном губитку видљивости. Ова разлика је важна за избор које ресурсе ослободити у свакој фази.

КарактеристикаonPauseonStop
Степен видљивостиДелимично видљивоПотпуно невидљиво
ФокусИзгубљенИзгубљен
Време извршењаДо 500 msДо 5 s (ANR timeout)
Ресурси за ослобађањеКритични (медија, камера)Сви невидљиви (сензори, анимације, location)
ОпоравакonResumeonRestart → onStart → onResume
Приоритет процесаВисок (Foreground)Средњи (Background)

Опште правило: у onPause ослобађајте системске ресурсе који одмах утичу на корисничко искуство друге апликације (камера, медија плејер), у onStop — све остале ресурсе који нису потребни када је Activity скривена. Google препоручује у onPause чување критичних корисничких података (нацрт имејла, подешавања), јер onStop можда неће наступити при брзом пребацивању.

onStop → onRestart: повратак на екран

Када се корисник врати на скривену Activity, систем позива onRestart → onStart → onResume. Метод onRestart сигнализира да се Activity враћа из Stopped стања. Ово је важна фаза за обнављање UI и ресурса који су ослобођени у onStop.

Секвенца позива при повратку:

  • onRestart() — Activity се обавештава да ће поново бити приказана. Типичне радње: поновно учитавање података, ажурирање листи.
  • onStart() — Activity постаје видљива, али још увек није активна. Овде се поново иницијализују ресурси ослобођени у onStop.
  • onResume() — Activity добија фокус и спремна је за интеракцију. Покрећу се анимације, региструју сензори.

Ако је процес апликације убијен од стране система у стању Stopped, onCreate се позива уместо onRestart, а Bundle из onSaveInstanceState се прослеђује за обнављање стања. Овај сценарио (process death) — један од најчешћих узрока грешака у Android апликацијама: програмери имплементирају onRestart, али заборављају да узму у обзир обнављање путем onCreate након убијања процеса.

Примери кода са onStop у Kotlin-у

Пример 1: Основна имплементација onStop са ослобађањем сензора

Приказује коректно одјављивање са сензора и заустављање анимације при скривању Activity. Након повратка на екран, ресурси се обнављају у onStart.

kotlin
class MainActivity : AppCompatActivity() {
    private lateinit var sensorManager: SensorManager
    private var accelerometer: Sensor? = null
    private var rotationAnimator: ObjectAnimator? = null

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_main)
        sensorManager = getSystemService(Context.SENSOR_SERVICE) as SensorManager
        accelerometer = sensorManager.getDefaultSensor(Sensor.TYPE_ACCELEROMETER)
    }

    override fun onStart() {
        super.onStart()
        accelerometer?.let {
            sensorManager.registerListener(sensorListener, it, SensorManager.SENSOR_DELAY_NORMAL)
        }
        rotationAnimator = ObjectAnimator.ofFloat(findViewById(R.id.icon), "rotation", 0f, 360f)
        rotationAnimator?.apply {
            duration = 3000
            repeatMode = ValueAnimator.RESTART
            repeatCount = ValueAnimator.INFINITE
            start()
        }
    }

    override fun onStop() {
        super.onStop()
        sensorManager.unregisterListener(sensorListener)
        rotationAnimator?.cancel()
    }

    override fun onRestart() {
        super.onRestart()
        Log.d("MainActivity", "Activity се враћа из Stopped стања")
    }

    private val sensorListener = SensorEventListener { event, _ ->
        Log.d("MainActivity", "Accel: x=${event.values[0]}, y=${event.values[1]}, z=${event.values[2]}")
    }
}

Код региструје сензор акцелерометра и покреће бесконачну анимацију ротације у onStart. У onStop сензор се искључује и анимација се отказује — ово спречава трошење батерије када је Activity скривена. Након повратка кроз onRestart → onStart, ресурси се поново креирају.

Пример 2: onStop са чувањем стања путем SavedStateHandle

Модерни приступ са коришћењем ViewModel + SavedStateHandle. Подаци форме се аутоматски чувају при onStop без ручног Bundle-а.

kotlin
class FormViewModel(
    private val savedStateHandle: SavedStateHandle
) : ViewModel() {
    var email: String
        get() = savedStateHandle["email"] ?: ""
        set(value) { savedStateHandle["email"] = value }

    var message: String
        get() = savedStateHandle["message"] ?: ""
        set(value) { savedStateHandle["message"] = value }
}

class FormActivity : AppCompatActivity() {
    private val viewModel: FormViewModel by viewModels()

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_form)
        Log.d("FormActivity", "onCreate: email=${viewModel.email}")
    }

    override fun onStop() {
        super.onStop()
        Log.d("FormActivity", "onStop: подаци сачувани у SavedStateHandle")
    }
}

SavedStateHandle аутоматски чува вредности у Bundle при onSaveInstanceState, који се позива пре onStop. При ротацији екрана или убијању процеса, подаци се обнављају без губитка. Google препоручује SavedStateHandle за форме и нацрте уместо директног onSaveInstanceState.

Пример 3: lifecycleScope за операције у onStop

Коришћење lifecycleScope са корутинама за асинхроно чување података при преласку у onStop. Корутина се покреће у IO dispatcher-у, не блокирајући главну нит.

kotlin
class NoteActivity : AppCompatActivity() {
    private val noteRepository = NoteRepository()

    override fun onStop() {
        lifecycleScope.launch(Dispatchers.IO) {
            val text = findViewById<EditText>(R.id.note_content).text.toString()
            noteRepository.saveDraft(text)
            withContext(Dispatchers.Main) {
                Log.d("NoteActivity", "Нацрт сачуван у onStop")
            }
        }
        super.onStop()
    }
}

Корутина lifecycleScope.launch се аутоматски отказује ако се животни циклус Activity заврши. Коришћење Dispatchers.IO гарантује да упис у базу или датотеку не блокира повратак на Activity. Према Google-у, корутине у lifecycleScope су пожељан начин за асинхроне операције у onStop.

Често постављана питања

По чему се onStop разликује од onDestroy?

onStop — Activity престаје да буде видљива, али остаје у меморији у стању Stopped. Систем може вратити Activity путем onRestart. onDestroy — Activity се уништава, меморија се ослобађа. Након onDestroy повратак је могућ само кроз креирање нове инстанце Activity (onCreate).

Да ли је обавезно позвати super.onStop()?

Да, обавезно. super.onStop() обезбеђује коректно функционисање системских компоненти: фрагмената, LoaderManager-а, ViewModelStore-а. Пропуштање super.onStop() може изазвати цурење меморије и некоректан опоравак фрагмената. Увек позивајте super.onStop() последњи или први — редослед није критичан, али позив је обавезан.

Како проверити да је onStop позван?

Користите Log.d или Timber у свакој методи животног циклуса. Укључите филтер logcat по tag-у ваше Activity. За продукцију користите Android Vitals — Google аутоматски прикупља метрике животног циклуса и приказује аномалије у Play Console. Такође је доступан мониторинг животног циклуса путем ProcessLifecycleOwner.

Шта се дешава ако се у onStop баци изузетак?

Неухваћени изузетак у onStop изазива Force Close апликације. Систем не хвата изузетке у callback-има животног циклуса. Ако се у onStop извршавају операције које могу бацити изузетак (рад са датотекама, мрежом), обавите их у try-catch и забележите грешку, не прекидајући извршење super.onStop().

Да ли треба ослободити Bitmap у onStop?

Не, Bitmap у Activity ће бити сакупљен од стране GC ако нема референци на њега. Присилно ослобађање (recycle()) у onStop није потребно и чак је штетно — ако се Activity врати путем onRestart, Bitmap ће морати поново да се учита. Користите Glide или Coil за учитавање слика — ове библиотеке аутоматски управљају кешом и животним циклусом.

Резиме

  • onStop — метод животног циклуса Activity, који се позива при потпуном губитку видљивости. Activity остаје у меморији у стању Stopped.
  • Након onStop могућа су два сценарија: onRestart (повратак на екран) или onDestroy (уништавање Activity).
  • У onStop је потребно ослободити сензоре, анимације, камеру, location слушаоце — све што није потребно када је Activity невидљива.
  • onStop се разликује од onPause по степену видљивости: onPause — делимични, onStop — потпуни губитак видљивости.
  • onSaveInstanceState се позива пре onStop — користите га за чување пролазног UI стања.
  • Корутине lifecycleScope са Dispatchers.IO — пожељан начин за асинхроне операције у onStop.
  • Увек позивајте super.onStop() и обавите опасне операције у try-catch да бисте избегли Force Close.

Развићемо мобилну апликацију под кључ

IT Sectr креира iOS и Android апликације за стартапе и предузећа од 2017. године. Саветоваћемо вас и предложити најбоље решење.

Разговарајте о пројекту

Прочитајте такође