onStart est une méthode du cycle de vie Android qui est appelée lorsqu’une Activity ou un Fragment devient visible pour l’utilisateur. À ce moment, l’écran apparaît sur l’affichage de l’appareil, mais ne peut pas encore interagir avec l’utilisateur — le focus de saisie est absent jusqu’à l’appel de onResume. La méthode onStart est idéale pour enregistrer des écouteurs système, se connecter aux services de géolocalisation et lancer des animations qui doivent fonctionner tant que le composant est visible à l’écran. En savoir plus sur le cycle de vie complet d’Activity dans l’article Activity Lifecycle.
Points clés
onStart est la deuxième méthode du cycle de vie d’Activity, appelée par le système après onCreate (ou après onRestart lors du retour d’un état arrêté). Au moment de l’appel de onStart, l’Activity ou le Fragment devient visible à l’écran. L’utilisateur voit l’interface, mais l’écran n’est pas encore prêt pour l’interaction — le focus de saisie n’apparaîtra qu’après onResume.
La méthode onStart fait partie de la « durée de vie visible » (visible lifetime) d’une Activity — l’intervalle entre onStart et onStop. Pendant cette période, l’Activity peut être partiellement couverte par d’autres fenêtres (par exemple, une Activity transparente ou une fenêtre de dialogue), mais son UI reste visible. Cela distingue la durée de vie visible de la « durée de vie au premier plan » (onResume — onPause), lorsque l’Activity a le focus de saisie complet.
Comprendre cette hiérarchie à trois niveaux est essentiel pour une répartition correcte du code. onCreate — initialisation unique, onStart — connexion des ressources visibles, onResume — accès exclusif aux ressources exclusives. Un développeur qui confond ces niveaux risque de créer des fuites mémoire ou un comportement incorrect de l’application lors du changement d’écrans.
Dans Activity, la méthode onStart est appelée chaque fois que l’écran apparaît sur l’affichage — aussi bien au premier lancement (après onCreate) qu’au retour de l’arrière-plan (après onRestart). Contrairement à onCreate, onStart peut être appelé plusieurs fois pendant la durée de vie d’une instance d’Activity, donc le code qui doit s’exécuter chaque fois que l’écran apparaît est placé ici.
class DashboardActivity : AppCompatActivity() {
private val connectivityReceiver = object : BroadcastReceiver() {
override fun onReceive(context: Context?, intent: Intent?) {
val isConnected = ... // Vérification de 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()
}
}
Règle clé : toutes les ressources connectées dans onStart doivent être libérées dans onStop. Cela garantit que lorsque l’Activity est cachée de l’écran, elle ne consomme pas de batterie, n’écoute pas les événements système et n’occupe pas de mémoire. Android Studio inclut des règles lint qui avertissent de l’enregistrement d’un BroadcastReceiver sans désenregistrement correspondant.
onStart dans Fragment est étroitement lié au cycle de vie de l’Activity conteneur. Le Fragment reçoit l’appel onStart après que l’Activity qui le contient a reçu onStart. Cependant, si le Fragment est ajouté en mode différé (FragmentTransaction.commit() sans addToBackStack), onStart peut être appelé avec un retard.
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()
}
}
Spécificités de Fragment.onStart : si le Fragment se trouve dans un ViewPager avec offscreenPageLimit = 1, les fragments voisins recevront également onStart avant de devenir visibles. Cela peut entraîner un enregistrement prématuré des écouteurs. Pour ces cas, utilisez la méthode setUserVisibleHint() ou vérifiez isVisible dans onStart pour n’enregistrer les écouteurs que pour les fragments réellement visibles.
La principale différence entre onStart et onResume est le niveau d’activité de l’écran. onStart signale que l’Activity est visible à l’écran mais pas nécessairement au premier plan. onResume signale que l’Activity est au premier plan et a le focus de saisie. La différence est démontrée par un exemple de fenêtre de dialogue : lorsqu’un Dialog apparaît au-dessus d’une Activity, l’Activity perd onResume (onPause est appelé) mais reste visible — onStart/onStop ne sont pas appelés.
Le tableau comparatif montre clairement dans quels scénarios chaque méthode est appelée :
| Scénario | onStart | onResume |
|---|---|---|
| Lancement de l’application | Appelé | Appelé |
| Dialog ouvert sur Activity | Non appelé | onPause (perte de focus) |
| Bouton Accueil enfoncé | onStop (caché) | onPause → onStop |
| Retour des Récents | onStart (visible) | onResume (focus) |
| Rotation de l’écran | onCreate → onStart | → onResume |
| Appel entrant | onStop (caché) | onPause → onStop |
Ce tableau aide le développeur à décider dans quelle méthode placer un code spécifique. Par exemple, si l’application doit mettre en pause la lecture vidéo lors de tout chevauchement d’écran (même un dialogue), le code est placé dans onPause. Si la vidéo ne doit s’arrêter que lorsque l’écran est complètement caché — le code est placé dans onStop.
onStart est l’endroit optimal pour enregistrer les écouteurs qui ne doivent fonctionner que lorsque l’Activity est visible à l’écran. Cela concerne trois principaux types de composants système : BroadcastReceiver pour les événements système, LocationListener pour la géolocalisation et SensorListener pour les capteurs de l’appareil.
BroadcastReceiver est enregistré dynamiquement via Context.registerReceiver() dans onStart et désenregistré dans onStop via unregisterReceiver(). L’enregistrement dynamique est préférable à l’enregistrement statique (dans le manifeste) car il limite la durée de vie du récepteur à la période de visibilité de l’Activity — l’application ne se réveille pas avec les messages de broadcast système lorsque l’Activity est cachée.
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()
}
La géolocalisation et les capteurs sont des opérations gourmandes en ressources. Demander des mises à jour GPS dans onStart et les annuler dans onStop garantit que l’application ne consomme pas la batterie lorsque l’écran est caché. Pour un réglage fin, utilisez requestLocationUpdates avec un intervalle et une distance minimaux — par exemple, 10 secondes et 10 mètres, ce qui offre un équilibre optimal entre précision et consommation d’énergie.
Lancer des animations dans onStart, plutôt que dans onCreate, garantit que l’animation commence chaque fois que l’écran apparaît. Si vous lancez une animation dans onCreate, elle ne fonctionnera que lors de la première création de l’Activity, pas au retour de l’arrière-plan. onStart est appelé chaque fois que l’Activity devient visible, ce qui en fait l’endroit idéal pour lancer des animations cycliques et des transitions.
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()
}
Pour les animations utilisant ObjectAnimator ou ValueAnimator, il est important d’appeler cancel() dans onStop. Si l’animation continue de s’exécuter après que l’Activity est cachée, elle consomme inutilement des ressources GPU et CPU, dégradant les performances de l’appareil et accélérant l’épuisement de la batterie. Android Studio Profiler (graphique GPU) permet de suivre les animations actives et de détecter les fuites.
La règle de paire onStart/onStop s’applique également au travail avec l’appareil photo pour l’aperçu (CameraX). Ouvrir l’appareil photo dans onStart et le fermer dans onStop garantit que l’appareil photo n’est pas bloqué pour d’autres applications lorsque votre application n’est pas visible à l’écran. La violation de cette règle est une cause fréquente d’avis négatifs sur Google Play.
Foire aux questions
onStart — pour les écouteurs qui doivent fonctionner tant que l’écran est visible (BroadcastReceiver, LocationListener, SensorListener). onResume — pour les ressources nécessitant un accès exclusif (appareil photo, capture vidéo, reconnaissance vocale). Les écouteurs d’événements système ne nécessitent pas d’accès exclusif et peuvent fonctionner avec un chevauchement partiel — ils sont enregistrés dans onStart. L’appareil photo ne doit être actif qu’avec un focus complet — il est ouvert dans onResume.
onStart est toujours appelé si l’Activity passe dans un état visible. Le seul scénario sans onStart — l’Activity est créée et immédiatement terminée (par exemple, en raison d’une erreur dans onCreate). Dans ce cas, onDestroy est appelé juste après onCreate. Mais c’est un scénario d’urgence qui ne devrait pas se produire dans un code correctement écrit.
Oui, onStart peut ne pas recevoir onResume si une autre Activity ou une fenêtre transparente s’ouvre immédiatement au-dessus de l’Activity. Par exemple, si un écran d’autorisation est lancé après onCreate (Activity A → Activity B), dans Activity A, onStart est appelé, mais pas onResume — elle reçoit immédiatement onPause → onStop lorsqu’elle est recouverte par l’écran B.
onStart peut être appelé plusieurs fois pendant la durée de vie d’une instance d’Activity. Chaque fois que l’Activity passe d’un état caché (onStop) à un état visible, onStart est appelé. En pratique, avec une utilisation active de l’application, onStart peut être appelé des dizaines ou des centaines de fois par session.
Charger des données dans onStart est justifié si les données doivent être mises à jour chaque fois que l’écran apparaît. Par exemple, un fil d’actualités ou une liste de notifications. Cependant, le chargement doit être asynchrone — via des coroutines avec lifecycleScope, pour ne pas bloquer le thread UI. Pour les données qui ne changent pas entre les apparitions de l’écran, un chargement unique dans onCreate est suffisant.
Résumé
Nous développerons une application mobile clé en main
IT Sectr crée des applications iOS et Android pour les startups et les entreprises depuis 2017. Nous vous conseillerons et vous proposerons la meilleure solution.
Lisez aussi