onStop — ce este, ascunderea Activity în ciclul de viață Android

Autor: IT Sectr Publicat: 2026-03-04 Timp de citire: 9 min

onStop — metoda ciclului de viață al Activity în Android, apelată de sistem când Activity nu mai este vizibilă pentru utilizator. Activity trece în starea Stopped după ce o nouă Activity o acoperă complet sau la minimizarea aplicației. În metoda onStop, dezvoltatorul este obligat să oprească animațiile, să elibereze resursele camerei și senzorilor, să salveze ciornele datelor introduse. Conform Android Vitals (Google, 2025), gestionarea corectă a onStop reduce numărul de ANR (Application Not Responding) la minimizarea aplicației cu 35%. După onStop, sistemul poate apela onRestart (revenirea pe ecran) sau onDestroy (încheierea completă). Documentația Android Developers despre ciclul de viață al Activity descrie onStop ca granița dintre starea vizibilă și cea invizibilă.

Principalele puncte

  • onStop — metoda apelată la pierderea completă a vizibilității Activity, dar Activity se află încă în memorie.
  • După onStop, Activity trece în starea Stopped — vie în memorie, dar nu este vizibilă și nu interacționează cu utilizatorul.
  • Sistemul poate apela onRestart → onStart → onResume la revenirea pe Activity sau onDestroy la încheiere.
  • În onStop trebuie eliberate resursele: oprite animațiile, dezactivate senzorii și camera, salvate datele intermediare.
  • Implementarea corectă a onStop — factor cheie al stabilității aplicației în multitasking și la minimizare.

Ce este onStop în Android?

onStop — este un callback al clasei AppCompatActivity (și al predecesorului său Activity), care este apelat de sistemul de operare Android atunci când Activity încetează să mai fie complet vizibilă pentru utilizator. În acest moment, Activity este ascunsă de o altă Activity, o fereastră de dialog, lansatorul de sistem sau ecranul de blocare. Din perspectiva ciclului de viață, onStop urmează după onPause și semnalează că Activity nu mai este vizibilă pe ecran, deși obiectul Activity și starea sa rămân în memorie.

Când Activity trece în starea Stopped (oprită), își păstrează starea în memoria RAM — toate câmpurile, ierarhia View și ViewModel rămân accesibile. Acest lucru deosebește Stopped de starea distrusă (Destroyed), în care Activity este eliminată complet. System UI poate ucide procesul aplicației aflate în starea Stopped la insuficiența memoriei — acesta este așa-numitul process death. Dezvoltatorul este obligat să salveze datele critice (ciorne, poziția de derulare) în onSaveInstanceState(), care este apelat înainte de onStop, pentru a garanta restaurarea la uciderea procesului.

Conform specificației Android Compatibility Definition Document (CDD) pentru versiunea 14+, procesul în starea Stopped are prioritate redusă la uciderea de către OOM Killer — mai mică decât procesele în faza Background, dar mai mare decât procesele din cache. Potrivit statisticilor Google, 68% din cazurile de ucidere a proceselor au loc când Activity se află în starea Stopped, nu Paused.

Când este apelat onStop: scenarii și ordine

onStop este apelat la pierderea completă a vizibilității Activity, indiferent de cauză: lansarea unei noi Activity peste cea curentă, minimizarea aplicației (apăsarea Home), blocarea ecranului, un apel primit sau deschiderea unui dialog de sistem. În toate aceste cazuri, Activity primește mai întâi onPause (pierderea parțială a focalizării), apoi onStop (pierderea completă a vizibilității).

Principalele scenarii de apelare a onStop:

  • Lansarea unei noi Activity peste cea curentă — Activity curentă primește onPause, apoi onStop; noua Activity trece prin onCreate → onStart → onResume.
  • Minimizarea aplicației (Home) — Activity trece în onPause → onStop în 200–300 ms, rămâne în memorie în starea Stopped.
  • Blocarea ecranului — sistemul apelează onPause → onStop, deoarece ecranul de blocare acoperă complet Activity.
  • Apel primit — Activity de telefon (Dialer) se lansează deasupra, Activity curentă trece în onStop.
  • Comutarea la altă aplicație (Recent Apps) — Activity este ascunsă, primește onStop, dar rămâne în cache-ul proceselor.

Este important de înțeles că onStop nu este apelat la rotirea ecranului — în acest caz, Activity este distrusă (onPause → onStop → onDestroy) și recreată (onCreate → onStart → onResume). Excepție — flagul android:configChanges="orientation" în manifest, la care Activity nu este recreată, ci primește apelul onConfigurationChanged().

onStop în ciclul de viață al Activity

onStop ocupă un loc central în secvența ciclului de viață al Activity între starea vizibilă și cea invizibilă. Secvența completă: onCreate → onStart → onResume → (stare activă) → onPause → onStop → onDestroy (sau onRestart → onStart → onResume la revenire).

StareMetodăVizibilitateInteracțiuneMemorie
CreatedonCreateNuNuAlocată
StartedonStartParțialNuCompletă
ResumedonResumeCompletăDaCompletă
PausedonPauseParțialNuCompletă
StoppedonStopNuNuCompletă*
DestroyedonDestroyNuNuEliberată

*În starea Stopped, Activity este păstrată în memorie, dar poate fi ucisă de sistem la insuficiența resurselor. Prioritatea uciderii proceselor Stopped — penultima, mai mare doar decât procesele goale din cache.

onStop și onSaveInstanceState: Sistemul apelează onSaveInstanceState(Bundle) înainte de onStop pentru a salva starea dinamică a UI. Dezvoltatorul suprascrie această metodă pentru a salva în Bundle valorile câmpurilor de intrare, poziția RecyclerView, elementele selectate. Chiar dacă Activity nu va fi distrusă (utilizatorul doar a minimizat și s-a întors), Bundle este transmis la onCreate la schimbările de configurare. Google recomandă salvarea doar a stării tranzitorii a UI — nu a datelor din repository sau ViewModel, care trăiesc în afara Activity.

Ce resurse să eliberați în onStop

În onStop, dezvoltatorul este obligat să elibereze toate resursele care nu sunt necesare când Activity nu este vizibilă. Aceasta reduce încărcarea bateriei, procesorului și memoriei și previne ANR la revenirea pe activitate.

Ce să eliberați în onStop:

  • Animații și transitions — opriți ObjectAnimator, ValueAnimator, ViewPropertyAnimator. O animație în funcțiune a unei Activity invizibile este o risipă de cicluri GPU.
  • Senzori (Sensors) — dezabonați-vă de la SensorManager (accelerometru, giroscop, magnetometru). Senzorii consumă energie chiar și când Activity este ascunsă.
  • Cameră și microfon — eliberați Camera2 sau CameraX, opriți MediaRecorder. A lăsa camera activă la o Activity ascunsă este interzis de politica Google Play.
  • LocationListener — dezabonați-vă de la FusedLocationProviderClient sau LocationManager. Geolocația este cea mai consumatoare resursă de energie.
  • Network listeners — închideți WebSocket, anulați cererile HTTP care nu sunt necesare în fundal.
  • MediaPlayer și ExoPlayer — puneți pe pauză sau opriți, dacă redarea nu trebuie să continue în fundal.

Ce să nu faceți în onStop: Nu efectuați operații lungi — salvarea datelor mari în BD, cereri de rețea, calcule complexe. onStop se execută pe firul principal și blochează revenirea pe Activity. Pentru operații lungi, utilizați WorkManager cu întârziere sau corutine în viewModelScope. Nu eliberați resursele ViewModel — ViewModel supraviețuiește onStop și va fi utilizat la revenire.

Diferența dintre onStop și onPause

onPause și onStop diferă prin gradul de pierdere a vizibilității și volumul acțiunilor obligatorii. onPause este apelat la pierderea parțială a focalizării (de exemplu, deschiderea unei ferestre de dialog sau a meniului de sistem), onStop — la pierderea completă a vizibilității. Această diferență este importantă pentru alegerea resurselor de eliberat la fiecare etapă.

CaracteristicăonPauseonStop
Grad de vizibilitateParțial vizibilComplet invizibil
FocalizarePierdutăPierdută
Timp de execuțiePână la 500 msPână la 5 s (timeout ANR)
Resurse de eliberatCritice (media, cameră)Toate invizibile (senzori, animații, location)
RestaurareonResumeonRestart → onStart → onResume
Prioritatea procesuluiRidicată (Foreground)Medie (Background)

Regula generală: în onPause eliberați resursele sistemice care afectează imediat experiența utilizatorului altei aplicații (cameră, player media), în onStop — toate celelalte resurse care nu sunt necesare când Activity este ascunsă. Google recomandă în onPause salvarea datelor critice ale utilizatorului (ciorna unui e-mail, setări), deoarece onStop poate să nu apară la comutarea rapidă.

onStop → onRestart: revenirea pe ecran

Când utilizatorul revine la Activity ascunsă, sistemul apelează onRestart → onStart → onResume. Metoda onRestart semnalează că Activity revine din starea Stopped. Aceasta este o etapă importantă pentru restaurarea UI și a resurselor care au fost eliberate în onStop.

Secvența de apeluri la revenire:

  • onRestart() — Activity este notificată că va fi afișată din nou. Acțiuni tipice: reîncărcarea datelor, actualizarea listelor.
  • onStart() — Activity devine vizibilă, dar încă nu este activă. Aici sunt reinițializate resursele eliberate în onStop.
  • onResume() — Activity primește focalizarea și este gata de interacțiune. Sunt pornite animațiile, sunt înregistrați senzorii.

Dacă procesul aplicației a fost ucis de sistem în starea Stopped, onCreate este apelat în loc de onRestart, iar Bundle din onSaveInstanceState este transmis pentru restaurarea stării. Acest scenariu (process death) — una dintre cele mai frecvente cauze de erori în aplicațiile Android: dezvoltatorii implementează onRestart, dar uită să ia în considerare restaurarea prin onCreate după uciderea procesului.

Exemple de cod cu onStop în Kotlin

Exemplul 1: Implementarea de bază a onStop cu eliberarea senzorilor

Demonstrează dezabonarea corectă de la senzori și oprirea animației la ascunderea Activity. După revenirea pe ecran, resursele sunt restaurate în 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 revine din starea Stopped")
    }

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

Codul înregistrează senzorul de accelerometru și pornește o animație infinită de rotație în onStart. În onStop, senzorul este dezactivat și animația anulată — aceasta previne consumul bateriei când Activity este ascunsă. După revenirea prin onRestart → onStart, resursele sunt recreate.

Exemplul 2: onStop cu salvarea stării prin SavedStateHandle

Abordare modernă cu utilizarea ViewModel + SavedStateHandle. Datele formularului sunt salvate automat la onStop fără Bundle manual.

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: date salvate în SavedStateHandle")
    }
}

SavedStateHandle salvează automat valorile în Bundle la onSaveInstanceState, care este apelat înainte de onStop. La rotirea ecranului sau uciderea procesului, datele sunt restaurate fără pierderi. Google recomandă SavedStateHandle pentru formulare și ciorne în loc de onSaveInstanceState direct.

Exemplul 3: lifecycleScope pentru operații în onStop

Utilizarea lifecycleScope cu corutine pentru salvarea asincronă a datelor la trecerea în onStop. Corutina este lansată în dispatcherul IO, neblocând firul principal.

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", "Ciorna salvată în onStop")
            }
        }
        super.onStop()
    }
}

Corutina lifecycleScope.launch este anulată automat dacă ciclul de viață al Activity se încheie. Utilizarea Dispatchers.IO garantează că scrierea în BD sau fișier nu blochează revenirea pe Activity. Potrivit Google, corutinele în lifecycleScope sunt modalitatea preferată pentru operații asincrone în onStop.

Întrebări frecvente

Cu ce diferă onStop de onDestroy?

onStop — Activity încetează să mai fie vizibilă, dar rămâne în memorie în starea Stopped. Sistemul poate readuce Activity prin onRestart. onDestroy — Activity este distrusă, memoria este eliberată. După onDestroy, revenirea este posibilă doar prin crearea unei noi instanțe a Activity (onCreate).

Este obligatorie apelarea super.onStop()?

Da, obligatorie. super.onStop() asigură funcționarea corectă a componentelor sistemice: fragmente, LoaderManager, ViewModelStore. Omiterea super.onStop() poate provoca scurgeri de memorie și restaurarea incorectă a fragmentelor. Apelați întotdeauna super.onStop() ultimul sau primul — ordinea nu este critică, dar apelul este obligatoriu.

Cum verific dacă onStop a fost apelat?

Folosiți Log.d sau Timber în fiecare metodă a ciclului de viață. Activați filtrul logcat după tagul Activity dumneavoastră. Pentru producție, utilizați Android Vitals — Google colectează automat metricile ciclului de viață și afișează anomalii în Play Console. De asemenea, este disponibilă monitorizarea ciclului de viață prin ProcessLifecycleOwner.

Ce se întâmplă dacă în onStop este aruncată o excepție?

O excepție neprinsă în onStop provoacă Force Close al aplicației. Sistemul nu prinde excepțiile în callback-urile ciclului de viață. Dacă în onStop se execută operații care pot arunca excepții (lucrul cu fișiere, rețea), înfășurați-le în try-catch și înregistrați eroarea fără a întrerupe execuția super.onStop().

Trebuie eliberat Bitmap în onStop?

Nu, Bitmap-ul din Activity va fi colectat de GC dacă nu există referințe către el. Eliberarea forțată (recycle()) în onStop nu este necesară și chiar dăunătoare — dacă Activity revine prin onRestart, Bitmap va trebui încărcat din nou. Folosiți Glide sau Coil pentru încărcarea imaginilor — aceste biblioteci gestionează automat cache-ul și ciclul de viață.

Rezumat

  • onStop — metoda ciclului de viață al Activity, apelată la pierderea completă a vizibilității. Activity rămâne în memorie în starea Stopped.
  • După onStop sunt posibile două scenarii: onRestart (revenirea pe ecran) sau onDestroy (distrugerea Activity).
  • În onStop trebuie eliberați senzorii, animațiile, camera, location-listener-ii — tot ce nu este necesar când Activity este invizibilă.
  • onStop diferă de onPause prin gradul de vizibilitate: onPause — pierdere parțială, onStop — pierdere completă a vizibilității.
  • onSaveInstanceState este apelat înainte de onStop — utilizați-l pentru salvarea stării tranzitorii a UI.
  • Corutinele lifecycleScope cu Dispatchers.IO — modalitatea preferată pentru operații asincrone în onStop.
  • Apelați întotdeauna super.onStop() și înfășurați operațiile periculoase în try-catch pentru a evita Force Close.

Vom dezvolta o aplicație mobilă la cheie

IT Sectr creează aplicații iOS și Android pentru startup-uri și afaceri din 2017. Vă vom consilia și vă vom propune cea mai bună soluție.

Discutați proiectul

Citiți și