onResume è un metodo del ciclo di vita di Android che viene chiamato quando un'Activity o un Fragment va in primo piano e riceve il focus di input. In questo stato, lo schermo è pronto per l'interazione con l'utente: tutti gli eventi tattili, le pressioni dei tasti e i gesti vengono indirizzati a questo componente. onResume è lo stato di lavoro di un'Activity, dove l'applicazione passa la maggior parte del tempo. È qui che si apre la fotocamera, si avvia la riproduzione video, si inizia il riconoscimento vocale e si registrano i listener di sensori che richiedono accesso esclusivo. Per maggiori informazioni sul ciclo di vita completo di un'Activity, leggi l'articolo Activity Lifecycle.
Punti chiave
onResume — il terzo metodo del ciclo di vita di un'Activity, chiamato dopo onStart, che segnala che lo schermo è pronto per l'interazione completa con l'utente. In questo momento, l'Activity è in cima alla pila delle attività (back stack), il sistema le indirizza tutti gli eventi di input e l'applicazione può iniziare qualsiasi operazione che richieda la partecipazione attiva dell'utente: videochiamate, giochi, registrazione audio, disegno su Canvas.
onResume fa parte della “vita in primo piano” (foreground lifetime) — l'intervallo tra onResume e onPause. Questo è il periodo più attivo di un'Activity, quando l'applicazione consuma più risorse: CPU per l'elaborazione tattile, GPU per il rendering delle animazioni, fotocamera e microfono per l'acquisizione video. Comprendere questo livello del ciclo di vita è fondamentale per ottimizzare il consumo energetico — le risorse aperte in onResume devono essere immediatamente chiuse in onPause.
Secondo Google I/O 2025, il tempo medio che un'Activity trascorre nello stato onResume per sessione è di 2–5 minuti per le applicazioni di notizie e di 15–30 minuti per giochi e messaggistica. Tutto il resto del tempo, l'Activity si trova negli stati onPause, onStop o onDestroy. Ciò significa che ottimizzare specificamente il codice onResume offre i maggiori vantaggi in termini di prestazioni e durata della batteria.
In un'Activity, il metodo onResume viene chiamato ogni volta che lo schermo riceve il focus di input — al primo avvio, quando si ritorna da un'altra Activity, quando si chiude un dialogo, quando si sblocca il dispositivo. Questo è un metodo “caldo” che può essere chiamato più volte per sessione e la sua implementazione deve essere il più leggera possibile.
class CameraActivity : AppCompatActivity() {
private var cameraProvider: ProcessCameraProvider? = null
private var preview: Preview? = null
override fun onResume() {
super.onResume()
val cameraProviderFuture = ProcessCameraProvider.getInstance(this)
cameraProviderFuture.addListener({
cameraProvider = cameraProviderFuture.get()
val cameraSelector = CameraSelector.DEFAULT_BACK_CAMERA
preview = Preview.Builder().build().also {
it.setSurfaceProvider(binding?.viewFinder?.surfaceProvider)
}
try {
cameraProvider?.unbindAll()
cameraProvider?.bindToLifecycle(
this, cameraSelector, preview
)
} catch (e: Exception) {
Log.e("Camera", "Failed to bind camera", e)
}
}, ContextCompact.getMainExecutor(this))
}
override fun onPause() {
super.onPause()
cameraProvider?.unbindAll()
preview = null
}
}
L'esempio con CameraX dimostra l'uso classico di onResume/onPause: la fotocamera è una risorsa esclusiva che può essere utilizzata da una sola applicazione alla volta. Legare la fotocamera al ciclo di vita tramite bindToLifecycle chiude automaticamente la fotocamera in onPause, ma una chiamata esplicita a unbindAll garantisce il rilascio immediato. Questo è particolarmente importante quando si passa tra Activities: la fotocamera deve essere rilasciata prima che un'altra Activity tenti di aprirla.
onResume in un Fragment viene chiamato dopo che l'Activity che lo contiene ha ricevuto onResume. Tuttavia, a causa delle peculiarità di FragmentManager e ViewPager, il momento della chiamata onResume per un Fragment può essere ritardato rispetto all'Activity. Ad esempio, un Fragment in un ViewPager con offscreenPageLimit = 1 riceve onResume solo quando diventa la pagina corrente, non all'avvio dell'Activity.
class VideoPlayerFragment : Fragment() {
private var exoPlayer: ExoPlayer? = null
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
super.onViewCreated(view, savedInstanceState)
exoPlayer = ExoPlayer.Builder(requireContext()).build()
binding?.playerView?.player = exoPlayer
}
override fun onResume() {
super.onResume()
exoPlayer?.play()
if (userVisibleHint) {
startBiometricAuth()
}
}
override fun onPause() {
exoPlayer?.pause()
stopBiometricAuth()
super.onPause()
}
}
Il controllo di userVisibleHint in Fragment.onResume è rilevante per ViewPager: un Fragment può ricevere onResume ma essere nascosto da una pagina vicina (ad esempio, durante una transizione animata). In tali casi, avviare video o biometria in onResume senza verificare la visibilità porterà a comportamenti imprevisti. A partire da Fragment 1.5.0, si consiglia di utilizzare FragmentTransaction.setMaxLifecycle() per un controllo preciso del ciclo di vita dei fragment in ViewPager2.
Gli sviluppatori spesso confondono onStart e onResume, posizionando il codice nel metodo sbagliato. La regola principale: onStart — per le risorse che funzionano durante la visibilità; onResume — per le risorse che richiedono il focus di input. Esaminiamo scenari specifici e la scelta corretta del metodo.
| Operazione | Metodo | Motivazione |
|---|---|---|
| Sottoscrizione geolocalizzazione | onStart / onStop | Il GPS può funzionare con visibilità parziale |
| Aprire la fotocamera | onResume / onPause | La fotocamera è una risorsa esclusiva |
| BroadcastReceiver | onStart / onStop | Gli eventi di sistema non richiedono focus |
| Riproduzione video | onResume / onPause | Il video deve essere visibile all'utente |
| Scansione Bluetooth | onStart / onStop | La scansione può essere eseguita in background |
| Registratore vocale (MediaRecorder) | onResume / onPause | La registrazione richiede UI attiva |
| Listener di sensori | onResume / onPause | Sensori per giochi e gesti |
| Aggiornamento dati | onStart | Dati aggiornati necessari alla comparsa |
Una regola pratica: se un'operazione deve essere interrotta quando appare un dialogo — usa onResume/onPause. Se un'operazione può continuare quando lo schermo è parzialmente coperto — usa onStart/onStop. Ad esempio, un lettore video deve mettere in pausa il video all'apertura di un dialogo (onPause), mentre la geolocalizzazione può continuare ad aggiornarsi (rimane in onStart).
Le risorse esclusive sono componenti del dispositivo che possono essere utilizzati da una sola applicazione in un dato momento. Fotocamera, microfono, uscita video (MediaProjection), adattatore NFC in modalità lettura, dispositivi USB in modalità accessorio — tutte queste risorse devono essere aperte in onResume e rilasciate in onPause.
MediaRecorder viene utilizzato per registrare audio e video. Le richieste di autorizzazione e la preparazione di MediaRecorder vengono effettuate in onCreate, mentre l'avvio della registrazione in onResume. Se l'utente passa a un'altra applicazione, onPause mette in pausa la registrazione e onResume la riprende. Questo è il comportamento standard per i registratori vocali e le applicazioni di registrazione video.
private var mediaRecorder: MediaRecorder? = null
private var isRecording = false
override fun onResume() {
super.onResume()
if (isRecording) {
mediaRecorder?.resume()
}
}
override fun onPause() {
if (isRecording) {
mediaRecorder?.pause()
}
super.onPause()
}
L'autenticazione biometrica (BiometricPrompt) dovrebbe essere chiamata solo quando l'Activity è in onResume. Se chiamata in onCreate o onStart, il dialogo biometrico potrebbe apparire prima che l'Activity abbia completato l'inizializzazione, portando a una gestione errata del risultato. Chiamarla in onResume garantisce che la finestra biometrica venga mostrata nel contesto corretto.
Esaminiamo tre pattern collaudati per lavorare con onResume utilizzati in progetti commerciali: ripristino del timer di inattività, aggiornamento dei dati visibili e integrazione con Jetpack Navigation.
Nelle applicazioni con dati sensibili (bancari, cartelle cliniche), onResume viene utilizzato per ripristinare il timer di logout automatico. Se l'utente interagisce attivamente con l'applicazione, onResume viene chiamato ad ogni transizione dello schermo e il timer viene ripristinato. Se l'utente minimizza l'applicazione, onPause ferma il timer e onResume al ritorno lo ripristina o richiede una nuova autenticazione.
Un elenco che deve visualizzare dati aggiornati ogni volta che si torna sullo schermo viene aggiornato in onResume. Ad esempio, se l'utente ha creato una nuova voce in un'altra Activity ed è tornato indietro, onResume ricarica l'elenco dal database locale o dalla cache ViewModel. Ciò garantisce la coerenza dei dati senza chiamate manuali a notifyDataSetChanged.
override fun onResume() {
super.onResume()
// ActivityResultLauncher ha restituito un risultato — aggiornamento dell'elenco
viewModel.refreshList()
// Ripristino del timer di inattività
inactivityTimer.reset()
}
In Jetpack Navigation, onResume di un fragment viene chiamato ogni volta che si ritorna ad esso tramite la navigazione indietro. Questa proprietà viene utilizzata per ripristinare lo stato dell'interfaccia: nascondere la tastiera, pulire i campi di ricerca, aggiornare il titolo della barra degli strumenti. OnBackPressedCallback in combinazione con onResume offre il controllo completo sulla navigazione senza duplicazione di codice.
Domande frequenti
onStart — lo schermo è visibile. onResume — lo schermo è attivo e pronto per l'interazione. Immaginate: state guardando la TV (onStart), ma prendete il telecomando (onResume). La TV è sempre visibile, ma l'interazione inizia solo con il telecomando. Se qualcuno copre la TV con una tenda — lo schermo smette di essere visibile (onStop). Se qualcuno vi toglie il telecomando — l'interazione cessa (onPause), ma la TV è ancora visibile.
onResume viene chiamato ogni volta che l'Activity riceve il focus di input. Il minimo è una volta (all'avvio). Il massimo dipende dagli scenari di utilizzo: passaggio tra schermate, apertura di dialoghi, blocco e sblocco rapido del dispositivo — ciascuno di questi scenari chiama onResume al ritorno sullo schermo.
La fotocamera è una risorsa esclusiva disponibile per una sola applicazione alla volta. Se si apre la fotocamera in onCreate o onStart, rimarrà bloccata per le altre applicazioni anche quando l'applicazione è inattiva. onResume garantisce che la fotocamera sia aperta solo quando l'Activity è in primo piano e onPause la chiude immediatamente. Questo è uno standard di sviluppo Android, stabilito nella documentazione di CameraX e Camera2 API.
Sì, onResume potrebbe non verificarsi se un'Activity viene sovrapposta da un'altra Activity immediatamente dopo la comparsa. Ad esempio, l'Activity A avvia l'Activity B nel metodo onCreate o onStart. In questo caso, A riceve onStart → onPause → onStop, saltando onResume. Il sistema non chiama onResume perché l'Activity A non ha mai ricevuto il focus di input.
In onResume, non si dovrebbero eseguire operazioni sincrone lunghe: caricare grandi quantità di dati dalla rete, query SQL complesse, elaborazione di immagini. onResume viene eseguito nel thread dell'interfaccia e qualsiasi blocco più lungo di 100–200 ms causa un ritardo nella reattività dell'interfaccia. Tutte le operazioni pesanti devono essere asincrone — tramite coroutine, RxJava o WorkManager. Inoltre, non è raccomandato chiamare finish() in onResume senza controllo — ciò può portare a un ciclo infinito di ricreazione.
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