onStop — occultamento dell'Activity nel ciclo di vita Android

Autore: IT Sectr Pubblicato: 2026-03-04 Tempo di lettura: 9 min

onStop — un metodo del ciclo di vita dell'Activity in Android, chiamato dal sistema quando l'Activity cessa di essere visibile all'utente. L'Activity passa allo stato Stopped dopo che una nuova Activity la copre completamente, o quando l'app viene minimizzata. Nel metodo onStop, lo sviluppatore deve fermare le animazioni, rilasciare le risorse della fotocamera e dei sensori, e salvare le bozze dei dati inseriti. Secondo Android Vitals (Google, 2025), la gestione corretta di onStop riduce il numero di ANR (Application Not Responding) durante la minimizzazione dell'app del 35%. Dopo onStop, il sistema può chiamare onRestart (ritorno allo schermo) o onDestroy (terminazione completa). La documentazione Android Developers sul ciclo di vita dell'Activity descrive onStop come il confine tra stato visibile e invisibile.

Punti chiave

  • onStop — metodo chiamato quando l'Activity perde completamente la visibilità, ma l'Activity è ancora in memoria.
  • Dopo onStop, l'Activity passa allo stato Stopped — viva in memoria, ma non visibile e non interagisce con l'utente.
  • Il sistema può chiamare onRestart → onStart → onResume al ritorno all'Activity o onDestroy alla terminazione.
  • In onStop è necessario rilasciare risorse: fermare le animazioni, disattivare sensori e fotocamera, salvare i dati intermedi.
  • L'implementazione corretta di onStop è un fattore chiave per la stabilità dell'app durante il multitasking e la minimizzazione.

Cos'è onStop in Android?

onStop — un metodo callback della classe AppCompatActivity (e del suo predecessore Activity), chiamato dal sistema operativo Android quando l'Activity cessa di essere completamente visibile all'utente. In questo momento, l'Activity è nascosta da un'altra Activity, una finestra di dialogo, il launcher di sistema o la schermata di blocco. Dal punto di vista del ciclo di vita, onStop segue onPause e segnala che l'Activity non è più visibile sullo schermo, sebbene l'oggetto Activity e il suo stato rimangano in memoria.

Quando l'Activity passa allo stato Stopped (fermata), mantiene il suo stato nella RAM — tutti i campi, la gerarchia delle View e la ViewModel rimangono accessibili. Questo distingue Stopped dallo stato Destroyed (distrutto), dove l'Activity viene completamente rimossa. L'interfaccia di sistema può uccidere il processo dell'applicazione nello stato Stopped in caso di mancanza di memoria — questo è il cosiddetto process death (morte del processo). Lo sviluppatore deve salvare i dati critici (bozze, posizione di scorrimento) in onSaveInstanceState(), che viene chiamato prima di onStop, per garantire il ripristino in caso di morte del processo.

Secondo il Documento di Definizione di Compatibilità Android (CDD) per la versione 14+, un processo nello stato Stopped ha una priorità ridotta per essere ucciso dall'OOM Killer — inferiore ai processi in fase Background, ma superiore ai processi in cache. Secondo le statistiche di Google, il 68% dei casi di morte del processo si verifica quando l'Activity è nello stato Stopped, non Paused.

Quando viene chiamato onStop: scenari e ordine

onStop viene chiamato quando l'Activity perde completamente la visibilità, indipendentemente dal motivo: avvio di una nuova Activity sopra quella corrente, minimizzazione dell'app (pressione di Home), blocco dello schermo, chiamata in arrivo o apertura di un dialogo di sistema. In tutti questi casi, l'Activity riceve prima onPause (perdita parziale del focus), poi onStop (perdita totale di visibilità).

Scenari principali di chiamata di onStop:

  • Avvio di una nuova Activity sopra quella corrente — l'Activity corrente riceve onPause, poi onStop; la nuova Activity passa attraverso onCreate → onStart → onResume.
  • Minimizzazione dell'app (Home) — l'Activity passa a onPause → onStop in 200–300 ms, rimane in memoria nello stato Stopped.
  • Blocco dello schermo — il sistema chiama onPause → onStop perché la schermata di blocco copre completamente l'Activity.
  • Chiamata in arrivo — l'app telefonica (Dialer) si avvia sopra, l'Activity corrente passa a onStop.
  • Passaggio a un'altra app (App recenti) — l'Activity viene nascosta, riceve onStop, ma rimane nella cache dei processi.

È importante capire che onStop non viene chiamato durante la rotazione dello schermo — in questo caso, l'Activity viene distrutta (onPause → onStop → onDestroy) e ricreata (onCreate → onStart → onResume). L'eccezione è il flag android:configChanges="orientation" nel manifest, che impedisce la ricreazione dell'Activity e chiama invece onConfigurationChanged().

onStop nel ciclo di vita dell'Activity

onStop occupa un posto centrale nella sequenza del ciclo di vita dell'Activity tra lo stato visibile e invisibile. La sequenza completa: onCreate → onStart → onResume → (stato attivo) → onPause → onStop → onDestroy (o onRestart → onStart → onResume al ritorno).

StatoMetodoVisibilitàInterazioneMemoria
CreatedonCreateNoNoAllocata
StartedonStartParzialeNoCompleta
ResumedonResumeCompletaCompleta
PausedonPauseParzialeNoCompleta
StoppedonStopNoNoCompleta*
DestroyedonDestroyNoNoLiberata

*Nello stato Stopped, l'Activity viene mantenuta in memoria ma può essere uccisa dal sistema in caso di mancanza di risorse. La priorità di uccisione dei processi Stopped è la penultima, solo sopra i processi vuoti in cache.

onStop e onSaveInstanceState: Il sistema chiama onSaveInstanceState(Bundle) prima di onStop per salvare lo stato dinamico dell'interfaccia. Lo sviluppatore sovrascrive questo metodo per salvare nel Bundle i valori dei campi di input, la posizione della RecyclerView e gli elementi selezionati. Anche se l'Activity non viene distrutta (l'utente ha semplicemente minimizzato ed è tornato), il Bundle viene passato a onCreate durante i cambi di configurazione. Google raccomanda di salvare solo lo stato transitorio dell'interfaccia — non i dati del repository o della ViewModel, che vivono al di fuori dell'Activity.

Quali risorse rilasciare in onStop

In onStop, lo sviluppatore deve rilasciare tutte le risorse che non sono necessarie quando l'Activity non è visibile. Ciò riduce il carico su batteria, CPU e memoria, e previene anche ANR al ritorno all'attività.

Cosa rilasciare in onStop:

  • Animazioni e transizioni — fermare ObjectAnimator, ValueAnimator, ViewPropertyAnimator. Animazioni in esecuzione su un'Activity invisibile sprecano cicli GPU.
  • Sensori — annullare la registrazione da SensorManager (accelerometro, giroscopio, magnetometro). I sensori consumano energia anche quando l'Activity è nascosta.
  • Fotocamera e microfono — rilasciare Camera2 o CameraX, fermare MediaRecorder. Lasciare la fotocamera attiva con l'Activity nascosta è vietato dalla politica di Google Play.
  • LocationListener — annullare la registrazione da FusedLocationProviderClient o LocationManager. La geolocalizzazione è la risorsa più energivora.
  • Listener di rete — chiudere WebSocket, annullare le richieste HTTP che non sono necessarie in background.
  • MediaPlayer e ExoPlayer — mettere in pausa o fermare la riproduzione se non deve continuare in background.

Cosa non fare in onStop: Non eseguire operazioni lunghe — salvare grandi quantità di dati nel database, richieste di rete, calcoli complessi. onStop viene eseguito sul thread principale e blocca il ritorno all'Activity. Per operazioni lunghe, usa WorkManager con ritardo o coroutine in viewModelScope. Non rilasciare le risorse della ViewModel — la ViewModel sopravvive a onStop e verrà utilizzata al ritorno.

Differenza tra onStop e onPause

onPause e onStop differiscono nel grado di perdita di visibilità e nell'ambito delle azioni obbligatorie. onPause viene chiamato in caso di perdita parziale del focus (ad esempio, apertura di una finestra di dialogo o di un menu di sistema), onStop — in caso di perdita completa di visibilità. Questa differenza è importante per scegliere quali risorse rilasciare in ogni fase.

CaratteristicaonPauseonStop
Livello di visibilitàParzialmente visibileCompletamente invisibile
FocusPersoPerso
Tempo di esecuzioneFino a 500 msFino a 5 s (timeout ANR)
Risorse da rilasciareCritiche (media, fotocamera)Tutte invisibili (sensori, animazioni, posizione)
RipristinoonResumeonRestart → onStart → onResume
Priorità del processoAlta (Primo piano)Media (Sfondo)

Regola generale: in onPause, rilasciare le risorse di sistema che immediatamente influenzano l'esperienza utente di un'altra app (fotocamera, lettore multimediale); in onStop — tutte le altre risorse non necessarie quando l'Activity è nascosta. Google raccomanda di salvare i dati critici dell'utente (bozza email, impostazioni) in onPause, poiché onStop potrebbe non essere chiamato durante un cambio rapido.

onStop → onRestart: ritorno allo schermo

Quando l'utente torna a un'Activity nascosta, il sistema chiama onRestart → onStart → onResume. Il metodo onRestart segnala che l'Activity sta tornando dallo stato Stopped. Questa è una fase importante per ripristinare l'interfaccia e le risorse che sono state rilasciate in onStop.

Sequenza di chiamate al ritorno:

  • onRestart() — l'Activity viene notificata che sarà mostrata di nuovo. Azioni tipiche: ricaricare i dati, aggiornare le liste.
  • onStart() — l'Activity diventa visibile ma non ancora attiva. Qui le risorse rilasciate in onStop vengono reinizializzate.
  • onResume() — l'Activity ottiene il focus ed è pronta per l'interazione. Le animazioni vengono avviate, i sensori vengono registrati.

Se il processo dell'app è stato ucciso dal sistema nello stato Stopped, viene chiamato onCreate invece di onRestart e il Bundle da onSaveInstanceState viene passato per il ripristino dello stato. Questo scenario (morte del processo) è una delle cause più comuni di bug nelle app Android: gli sviluppatori implementano onRestart ma dimenticano di considerare il ripristino tramite onCreate dopo la morte del processo.

Esempi di codice con onStop in Kotlin

Esempio 1: Implementazione di base di onStop con rilascio dei sensori

Mostra la corretta cancellazione della registrazione dei sensori e l'arresto delle animazioni durante l'occultamento dell'Activity. Al ritorno allo schermo, le risorse vengono ripristinate in 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", "L'Activity torna dallo stato Stopped")
    }

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

Il codice registra il sensore dell'accelerometro e avvia un'animazione di rotazione infinita in onStart. In onStop, il sensore viene deregistrato e l'animazione viene annullata — ciò impedisce il consumo della batteria quando l'Activity è nascosta. Dopo il ritorno tramite onRestart → onStart, le risorse vengono ricreate.

Esempio 2: onStop con conservazione dello stato tramite SavedStateHandle

Un approccio moderno che utilizza ViewModel + SavedStateHandle. I dati del modulo vengono salvati automaticamente durante onStop senza gestione manuale del 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: dati salvati in SavedStateHandle")
    }
}

SavedStateHandle salva automaticamente i valori nel Bundle durante onSaveInstanceState, che viene chiamato prima di onStop. Durante la rotazione dello schermo o la morte del processo, i dati vengono ripristinati senza perdita. Google raccomanda SavedStateHandle per moduli e bozze invece di onSaveInstanceState diretto.

Esempio 3: lifecycleScope per operazioni in onStop

Utilizzo di lifecycleScope con coroutine per salvare i dati in modo asincrono durante la transizione a onStop. La coroutine viene eseguita sul dispatcher IO senza bloccare il thread principale.

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", "Bozza salvata in onStop")
            }
        }
        super.onStop()
    }
}

La coroutine lifecycleScope.launch viene automaticamente annullata se il ciclo di vita dell'Activity termina. L'uso di Dispatchers.IO garantisce che la scrittura nel database o nel file non blocchi il ritorno all'Activity. Secondo Google, le coroutine in lifecycleScope sono il metodo preferito per eseguire operazioni asincrone in onStop.

Domande frequenti

Qual è la differenza tra onStop e onDestroy?

onStop — l'Activity cessa di essere visibile ma rimane in memoria nello stato Stopped. Il sistema può riportare l'Activity tramite onRestart. onDestroy — l'Activity viene distrutta, la memoria viene liberata. Dopo onDestroy, il ritorno è possibile solo creando una nuova istanza dell'Activity (onCreate).

È obbligatorio chiamare super.onStop()?

Sì, obbligatorio. super.onStop() garantisce il corretto funzionamento dei componenti di sistema: frammenti, LoaderManager, ViewModelStore. Saltare super.onStop() può causare perdite di memoria e un ripristino errato dei frammenti. Chiamare sempre super.onStop() per ultimo o per primo — l'ordine non è critico, ma la chiamata è obbligatoria.

Come verificare che onStop sia stato chiamato?

Utilizzare Log.d o Timber in ogni metodo del ciclo di vita. Attivare il filtro logcat per tag della propria Activity. Per la produzione, utilizzare Android Vitals — Google raccoglie automaticamente le metriche del ciclo di vita e mostra le anomalie nella Play Console. Il monitoraggio del ciclo di vita è disponibile anche tramite ProcessLifecycleOwner.

Cosa succede se viene lanciata un'eccezione in onStop?

Un'eccezione non catturata in onStop causa un Force Close dell'app. Il sistema non cattura le eccezioni nei callback del ciclo di vita. Se in onStop vengono eseguite operazioni che possono lanciare eccezioni (operazioni su file, rete), racchiuderle in try-catch e registrare l'errore senza interrompere super.onStop().

È necessario rilasciare Bitmap in onStop?

No, il Bitmap nell'Activity verrà raccolto dal GC se non ci sono riferimenti ad esso. Il rilascio forzato (recycle()) in onStop non è necessario ed è persino dannoso — se l'Activity torna tramite onRestart, il Bitmap dovrebbe essere ricaricato. Utilizzare Glide o Coil per il caricamento delle immagini — queste librerie gestiscono automaticamente la cache e il ciclo di vita.

Riepilogo

  • onStop — metodo del ciclo di vita dell'Activity chiamato alla perdita completa di visibilità. L'Activity rimane in memoria nello stato Stopped.
  • Dopo onStop, sono possibili due scenari: onRestart (ritorno allo schermo) o onDestroy (distruzione dell'Activity).
  • In onStop, è necessario rilasciare sensori, animazioni, fotocamera, listener di posizione — tutto ciò che non serve quando l'Activity è invisibile.
  • onStop differisce da onPause nel livello di visibilità: onPause — perdita parziale, onStop — perdita completa di visibilità.
  • onSaveInstanceState viene chiamato prima di onStop — usarlo per salvare lo stato transitorio dell'interfaccia.
  • Coroutine di lifecycleScope con Dispatchers.IO — il metodo preferito per operazioni asincrone in onStop.
  • Chiamare sempre super.onStop() e racchiudere le operazioni pericolose in try-catch per evitare Force Close.

Svilupperemo un'applicazione mobile chiavi in mano

IT Sectr crea applicazioni iOS e Android per startup e aziende dal 2017. Ti consulteremo e ti proporremo la soluzione migliore.

Discuti il progetto

Leggi anche