onStart è un metodo del ciclo di vita Android che viene chiamato quando un’Activity o un Fragment diventa visibile all’utente. In questo momento, lo schermo appare sul display del dispositivo, ma non può ancora interagire con l’utente — il focus di input è assente fino alla chiamata di onResume. Il metodo onStart è ideale per registrare listener di sistema, connettersi a servizi di geolocalizzazione e avviare animazioni che devono funzionare mentre il componente è visibile sullo schermo. Scopri di più sul ciclo di vita completo dell’Activity nell’articolo Activity Lifecycle.
Punti chiave
onStart è il secondo metodo del ciclo di vita dell’Activity, chiamato dal sistema dopo onCreate (o dopo onRestart quando si ritorna da uno stato arrestato). Nel momento in cui viene chiamato onStart, l’Activity o il Fragment diventa visibile sullo schermo. L’utente vede l’interfaccia, ma lo schermo non è ancora pronto per l’interazione — il focus di input apparirà solo dopo onResume.
Il metodo onStart fa parte della “durata di vita visibile” (visible lifetime) di un’Activity — l’intervallo tra onStart e onStop. Durante questo periodo, l’Activity può essere parzialmente coperta da altre finestre (ad esempio, un’Activity trasparente o una finestra di dialogo), ma la sua UI rimane visibile. Questo distingue la durata di vita visibile dalla “durata di vita in primo piano” (onResume — onPause), quando l’Activity ha il focus di input completo.
Comprendere questa gerarchia a tre livelli è fondamentale per distribuire correttamente il codice. onCreate — inizializzazione una tantum, onStart — connessione delle risorse visibili, onResume — accesso esclusivo alle risorse esclusive. Uno sviluppatore che confonde questi livelli rischia di creare perdite di memoria o un comportamento errato dell’applicazione durante il passaggio tra schermate.
In Activity, il metodo onStart viene chiamato ogni volta che lo schermo appare sul display — sia al primo avvio (dopo onCreate) che al ritorno dallo sfondo (dopo onRestart). A differenza di onCreate, onStart può essere chiamato più volte durante la vita di un’istanza di Activity, quindi il codice che deve essere eseguito ogni volta che lo schermo appare viene inserito qui.
class DashboardActivity : AppCompatActivity() {
private val connectivityReceiver = object : BroadcastReceiver() {
override fun onReceive(context: Context?, intent: Intent?) {
val isConnected = ... // Verifica ConnectivityManager
binding?.statusIndicator?.setColor(
if (isConnected) Color.GREEN else Color.RED
)
}
}
override fun onStart() {
super.onStart()
registerReceiver(
connectivityReceiver,
IntentFilter(ConnectivityManager.CONNECTIVITY_ACTION)
)
SensorManager.getInstance().registerStepCounter()
}
override fun onStop() {
unregisterReceiver(connectivityReceiver)
SensorManager.getInstance().unregisterStepCounter()
super.onStop()
}
}
Regola chiave: tutte le risorse collegate in onStart devono essere rilasciate in onStop. Ciò garantisce che quando l’Activity è nascosta dallo schermo, non consumi batteria, non ascolti eventi di sistema e non occupi memoria. Android Studio include regole lint che avvertono sulla registrazione di un BroadcastReceiver senza la corrispondente deregistrazione.
onStart in Fragment è strettamente legato al ciclo di vita dell’Activity contenitore. Il Fragment riceve la chiamata onStart dopo che l’Activity che lo contiene ha ricevuto onStart. Tuttavia, se il Fragment viene aggiunto in modalità differita (FragmentTransaction.commit() senza addToBackStack), onStart può essere chiamato con ritardo.
class MapFragment : Fragment() {
private var mapView: MapView? = null
override fun onCreateView(
inflater: LayoutInflater,
container: ViewGroup?,
savedInstanceState: Bundle?
): View {
mapView = MapView(requireContext())
return mapView!!
}
override fun onStart() {
super.onStart()
mapView?.onStart()
LocationService.connect(requireContext())
}
override fun onStop() {
mapView?.onStop()
LocationService.disconnect()
super.onStop()
}
}
Specificità di Fragment.onStart: se il Fragment si trova in un ViewPager con offscreenPageLimit = 1, anche i frammenti vicini riceveranno onStart prima di diventare visibili. Ciò può portare a una registrazione prematura dei listener. Per questi casi, utilizzare il metodo setUserVisibleHint() o verificare isVisible all’interno di onStart per registrare i listener solo per i frammenti effettivamente visibili.
La differenza principale tra onStart e onResume è il livello di attività dello schermo. onStart segnala che l’Activity è visibile sullo schermo ma non necessariamente in primo piano. onResume segnala che l’Activity è in primo piano e ha il focus di input. La differenza è dimostrata con un esempio di finestra di dialogo: quando un Dialog appare sopra un’Activity, l’Activity perde onResume (viene chiamato onPause) ma rimane visibile — onStart/onStop non vengono chiamati.
La tabella comparativa mostra chiaramente in quali scenari viene chiamato ciascun metodo:
| Scenario | onStart | onResume |
|---|---|---|
| Avvio dell’applicazione | Chiamato | Chiamato |
| Dialog aperto su Activity | Non chiamato | onPause (perde focus) |
| Pulsante Home premuto | onStop (nascosto) | onPause → onStop |
| Ritorno da Recenti | onStart (visibile) | onResume (focus) |
| Rotazione dello schermo | onCreate → onStart | → onResume |
| Chiamata in arrivo | onStop (nascosto) | onPause → onStop |
Questa tabella aiuta lo sviluppatore a decidere in quale metodo inserire un codice specifico. Ad esempio, se l’applicazione deve mettere in pausa la riproduzione video durante qualsiasi sovrapposizione dello schermo (anche un dialogo), il codice viene inserito in onPause. Se il video deve fermarsi solo quando lo schermo è completamente nascosto — il codice viene inserito in onStop.
onStart è il luogo ottimale per registrare listener che devono funzionare solo mentre l’Activity è visibile sullo schermo. Ciò riguarda tre tipi principali di componenti di sistema: BroadcastReceiver per gli eventi di sistema, LocationListener per la geolocalizzazione e SensorListener per i sensori del dispositivo.
BroadcastReceiver viene registrato dinamicamente tramite Context.registerReceiver() in onStart e deregistrato in onStop tramite unregisterReceiver(). La registrazione dinamica è preferibile alla registrazione statica (nel manifest) perché limita la durata del ricevitore al periodo di visibilità dell’Activity — l’applicazione non si sveglia con messaggi di broadcast di sistema quando l’Activity è nascosta.
private val batteryReceiver = object : BroadcastReceiver() {
override fun onReceive(context: Context?, intent: Intent) {
val level = intent.getIntExtra(BatteryManager.EXTRA_LEVEL, -1)
binding?.batteryText?.text = "$level%"
}
}
override fun onStart() {
super.onStart()
registerReceiver(batteryReceiver, IntentFilter(Intent.ACTION_BATTERY_CHANGED))
}
override fun onStop() {
unregisterReceiver(batteryReceiver)
super.onStop()
}
Geolocalizzazione e sensori sono operazioni che consumano molte risorse. Richiedere aggiornamenti GPS in onStart e cancellarli in onStop garantisce che l’applicazione non consumi batteria quando lo schermo è nascosto. Per una regolazione fine, utilizzare requestLocationUpdates con un intervallo e una distanza minimi — ad esempio, 10 secondi e 10 metri, che offre un equilibrio ottimale tra precisione e consumo energetico.
Avviare le animazioni in onStart, anziché in onCreate, garantisce che l’animazione inizi ogni volta che lo schermo appare. Se si avvia un’animazione in onCreate, funzionerà solo alla prima creazione dell’Activity, non al ritorno dallo sfondo. onStart viene chiamato ogni volta che l’Activity diventa visibile, rendendolo il luogo ideale per avviare animazioni cicliche e transizioni.
private lateinit var pulseAnimator: ValueAnimator
override fun onStart() {
super.onStart()
pulseAnimator.start()
binding?.loadingIndicator?.animate()?.alpha(1f)?.start()
}
override fun onStop() {
pulseAnimator.cancel()
binding?.loadingIndicator?.animate()?.cancel()
super.onStop()
}
Per le animazioni che utilizzano ObjectAnimator o ValueAnimator, è importante chiamare cancel() in onStop. Se l’animazione continua a essere eseguita dopo che l’Activity è nascosta, consuma inutilmente risorse GPU e CPU, degradando le prestazioni del dispositivo e accelerando il consumo della batteria. Android Studio Profiler (grafico GPU) consente di tracciare le animazioni attive e rilevare le perdite.
La regola di accoppiamento onStart/onStop si applica anche al lavoro con la fotocamera per l’anteprima (CameraX). Aprire la fotocamera in onStart e chiuderla in onStop garantisce che la fotocamera non sia bloccata per altre applicazioni quando l’applicazione non è visibile sullo schermo. Violare questa regola è una causa comune di recensioni negative su Google Play.
Domande frequenti
onStart — per i listener che devono funzionare mentre lo schermo è visibile (BroadcastReceiver, LocationListener, SensorListener). onResume — per le risorse che richiedono accesso esclusivo (fotocamera, acquisizione video, riconoscimento vocale). I listener di eventi di sistema non richiedono accesso esclusivo e possono funzionare con sovrapposizione parziale — vengono registrati in onStart. La fotocamera dovrebbe essere attiva solo con piena messa a fuoco — viene aperta in onResume.
onStart viene sempre chiamato se l’Activity passa a uno stato visibile. L’unico scenario senza onStart — l’Activity viene creata e immediatamente terminata (ad esempio, a causa di un errore in onCreate). In questo caso, onDestroy viene chiamato subito dopo onCreate. Ma questo è uno scenario di emergenza che non dovrebbe verificarsi in codice correttamente scritto.
Sì, onStart potrebbe non ricevere onResume se un’altra Activity o una finestra trasparente si apre immediatamente sopra l’Activity. Ad esempio, se viene avviata una schermata di autorizzazione dopo onCreate (Activity A → Activity B), in Activity A viene chiamato onStart, ma non onResume — riceve immediatamente onPause → onStop quando viene sovrapposta dallo schermo B.
onStart può essere chiamato più volte durante la vita di un’istanza di Activity. Ogni volta che l’Activity passa da uno stato nascosto (onStop) a uno stato visibile, viene chiamato onStart. In pratica, con un uso attivo dell’applicazione, onStart può essere chiamato dozzine o centinaia di volte per sessione.
Caricare dati in onStart è giustificato se i dati devono essere aggiornati ogni volta che lo schermo appare. Ad esempio, un feed di notizie o un elenco di notifiche. Tuttavia, il caricamento deve essere asincrono — tramite coroutine con lifecycleScope, per non bloccare il thread UI. Per i dati che non cambiano tra le apparizioni dello schermo, è sufficiente caricarli una volta in onCreate.
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