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 — 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.
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:
È 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 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).
| Stato | Metodo | Visibilità | Interazione | Memoria |
|---|---|---|---|---|
| Created | onCreate | No | No | Allocata |
| Started | onStart | Parziale | No | Completa |
| Resumed | onResume | Completa | Sì | Completa |
| Paused | onPause | Parziale | No | Completa |
| Stopped | onStop | No | No | Completa* |
| Destroyed | onDestroy | No | No | Liberata |
*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.
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:
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.
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.
| Caratteristica | onPause | onStop |
|---|---|---|
| Livello di visibilità | Parzialmente visibile | Completamente invisibile |
| Focus | Perso | Perso |
| Tempo di esecuzione | Fino a 500 ms | Fino a 5 s (timeout ANR) |
| Risorse da rilasciare | Critiche (media, fotocamera) | Tutte invisibili (sensori, animazioni, posizione) |
| Ripristino | onResume | onRestart → onStart → onResume |
| Priorità del processo | Alta (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.
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:
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.
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.
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.
Un approccio moderno che utilizza ViewModel + SavedStateHandle. I dati del modulo vengono salvati automaticamente durante onStop senza gestione manuale del Bundle.
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.
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.
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
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).
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.
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.
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().
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
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.
Leggi anche