onDestroy — la méthode finale du cycle de vie d'Activity et de Fragment dans Android, appelée avant la destruction complète du composant. onDestroy signale que l'Activity ou le Fragment termine son travail : toutes les ressources doivent être libérées, les fragments imbriqués — détruits, le ViewModel — nettoyé. Selon Google, onDestroy est appelé dans 100 % des cas de terminaison d'Activity, mais lors de la mort du processus (process death), le système peut ignorer complètement l'appel à onDestroy. La documentation Android sur onDestroy souligne que cette méthode ne garantit pas l'invocation en cas de terminaison anormale.
Points Clés
onDestroy — une méthode de callback qu'Android appelle avant de détruire complètement une Activity ou un Fragment. C'est la dernière opportunité pour le développeur de libérer des ressources, d'annuler des opérations d'arrière-plan et de finaliser le travail avec les données. Après l'exécution d'onDestroy, l'instance Activity/Fragment est marquée pour le ramasse-miettes (GC) et ne peut plus être utilisée.
Raisons d'appeler onDestroy :
Selon les statistiques Google Android Vitals (2025), environ 12 % de tous les cas de destruction d'Activity sont dus à la rotation d'écran, 65 % à finish() et 23 % aux changements de configuration. Le pourcentage de morts de processus avec onDestroy ignoré est d'environ 5 — 8 % selon les appareils avec peu de RAM (moins de 4 Go).
onDestroy est appelé dans la plupart des scénarios standard, mais il existe des exceptions importantes que le développeur doit prendre en compte. Comprendre les garanties d'invocation d'onDestroy est critique pour l'architecture de l'application, en particulier pour sauvegarder des données et annuler des tâches WorkManager.
Quand onDestroy est appelé :
Quand onDestroy N'EST PAS appelé :
En raison de l'absence de garantie d'invocation d'onDestroy, Google recommande : ne comptez jamais sur onDestroy pour sauvegarder des données critiques. Utilisez onSaveInstanceState(), WorkManager ou Room avec sauvegarde automatique. onDestroy est pour libérer des ressources, pas pour la persistance.
onDestroy existe à la fois pour Activity et Fragment, mais avec des contrats différents. Le cycle de vie du Fragment est plus détaillé : en plus d'onDestroy, il y a onDestroyView (destruction de la hiérarchie de View) et onDetach (détachement de l'Activity).
| Composant | Méthodes de destruction | Ordre | ViewModel survit |
|---|---|---|---|
| Activity | onDestroy | onPause → onStop → onDestroy | Non (seulement si ViewModelStore n'est pas sauvegardé) |
| Fragment | onDestroyView, onDestroy, onDetach | onPause → onStop → onDestroyView → onDestroy → onDetach | Oui, si le Fragment n'est pas supprimé |
La différence clé : la View d'un Fragment est recréée plus souvent que le Fragment lui-même. Lors de la rotation d'écran, le Fragment passe par onDestroyView (destruction de la View), mais le Fragment lui-même et son ViewModel restent vivants. onDestroyView est l'endroit approprié pour nettoyer les références de View afin d'éviter les fuites mémoire. Le onDestroy de Fragment est analogue au onDestroy d'Activity, appelé lorsque le Fragment est complètement supprimé.
Les fragments enfants sont détruits avant le onDestroy du Fragment parent. Dans l'Activity, les fragments enfants reçoivent onDestroy lorsque le onDestroy de l'Activity parente est appelé. L'ordre est garanti : les fragments se terminent avant l'Activity qui les contient.
onDestroy est destiné à libérer toutes les ressources qui ne doivent pas survivre à l'Activity ou au Fragment. Contrairement à onStop, qui libère les ressources jusqu'au retour, onDestroy effectue le nettoyage final.
Liste de vérification des actions obligatoires dans onDestroy :
Ce qu'il NE FAUT PAS faire dans onDestroy : Ne sauvegardez pas de données dans onDestroy — utilisez onPause ou onSaveInstanceState. Ne démarrez pas de nouveau Service ou de tâches WorkManager — l'Activity sera détruite et vous ne pourrez pas suivre le résultat. N'essayez pas de mettre à jour l'interface utilisateur — la hiérarchie de View est déjà détruite ou en cours de destruction ; appeler findViewById() retournera null.
ViewModel est conçu pour survivre à onDestroy d'Activity lors de la rotation d'écran, mais être détruit avec l'Activity lors de finish(). Ce comportement asymétrique est la principale cause de confusion chez les développeurs.
Lors de la rotation d'écran :
Lors de finish() (l'utilisateur a appuyé sur « Retour ») :
Par conséquent, annuler viewModelScope dans onDestroy n'est pas nécessaire — ViewModel le fera lui-même. Si vous utilisez lifecycleScope (lié à l'Activity, pas à ViewModel), annulez-le dans onDestroy via lifecycleScope.cancel() ou gérez le Job manuellement.
Montre la gestion correcte de lifecycleScope dans une Activity : une coroutine est lancée pour surveiller l'état du réseau et annulée dans onDestroy.
class NetworkMonitorActivity : AppCompatActivity() {
private val networkCallback = object : ConnectivityManager.NetworkCallback() {
override fun onAvailable(network: Network) {
Log.d("NetworkMonitor", "Réseau disponible")
}
override fun onLost(network: Network) {
Log.d("NetworkMonitor", "Réseau perdu")
}
}
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_network)
val connectivityManager = getSystemService(ConnectivityManager::class.java)
connectivityManager.registerDefaultNetworkCallback(networkCallback)
lifecycleScope.launch {
Log.d("NetworkMonitor", "Surveillance réseau démarrée")
}
}
override fun onDestroy() {
super.onDestroy()
val connectivityManager = getSystemService(ConnectivityManager::class.java)
connectivityManager.unregisterNetworkCallback(networkCallback)
Log.d("NetworkMonitor", "onDestroy : callback annulé")
}
}
Dans onDestroy, l'enregistrement du callback réseau est annulé. lifecycleScope est annulé automatiquement lorsque le cycle de vie est détruit — une annulation séparée de la coroutine n'est pas requise. Le callback réseau doit être désenregistré, sinon il restera dans le système même après la destruction de l'Activity.
Un Fragment nettoie correctement les références de View dans onDestroyView, empêchant les fuites mémoire dues aux fermetures.
class ProfileFragment : Fragment() {
private var avatarView: ImageView? = null
private var progressBar: ProgressBar? = null
private val imageLoader = ImageLoader()
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
super.onViewCreated(view, savedInstanceState)
avatarView = view.findViewById(R.id.avatar)
progressBar = view.findViewById(R.id.progress)
loadProfile()
}
private fun loadProfile() {
viewLifecycleOwner.lifecycleScope.launch {
try {
progressBar?.visibility = View.VISIBLE
val bitmap = imageLoader.load("https://example.com/avatar.png")
avatarView?.setImageBitmap(bitmap)
} finally {
progressBar?.visibility = View.GONE
}
}
}
override fun onDestroyView() {
super.onDestroyView()
avatarView = null
progressBar = null
imageLoader.cancel()
}
override fun onDestroy() {
super.onDestroy()
Log.d("ProfileFragment", "onDestroy : Fragment complètement détruit")
}
}
Dans onDestroyView, les références de View sont mises à null — cela empêche les fuites mémoire si une fermeture dans imageLoader contient une référence à avatarView. Le Fragment lui-même et son ViewModel restent vivants jusqu'à onDestroy. imageLoader.cancel() annule le chargement si le Fragment quitte l'écran.
Utiliser isFinishing() permet de distinguer si l'Activity se termine par commande utilisateur ou pour recréation.
class AnalyticsActivity : AppCompatActivity() {
private val analytics = Analytics()
override fun onDestroy() {
if (isFinishing) {
Log.d("AnalyticsActivity", "Activity se termine avec finish() — envoi d'analyses")
analytics.sendSessionEnd()
} else {
Log.d("AnalyticsActivity", "Activity recréée (rotation/configuration) — pas d'envoi d'analyses")
}
super.onDestroy()
}
}
Vérifier isFinishing() est un modèle important pour les analyses, la journalisation et le nettoyage des données de session. Lors de la rotation, les événements de fin de session ne doivent pas être envoyés — l'utilisateur travaille toujours avec l'application. Selon Google Analytics, la vérification incorrecte de isFinishing() est la cause de 40 % des faux événements de session.
Questions Fréquentes
Oui, cela peut arriver — lors de la mort du processus par le système, de l'arrêt forcé par l'utilisateur ou d'une terminaison anormale. Selon Google, environ 5 — 8 % des terminaisons d'Activity se produisent sans qu'onDestroy soit appelé. Les développeurs ne doivent pas compter sur onDestroy pour sauvegarder des données critiques — utilisez onPause ou onSaveInstanceState.
finish() — un appel qui initie la destruction de l'Activity. onDestroy — un callback qui est appelé pendant l'exécution de finish(). finish() est nécessaire pour qu'onDestroy soit appelé lors d'une terminaison normale. finish() peut être appelé par le système ou le développeur, onDestroy est seulement un callback système.
Oui, absolument à la fois dans Activity et Fragment. super.onDestroy() assure le nettoyage correct de ChildFragmentManager, LoaderManager et d'autres composants système. Sauter super.onDestroy() entraîne des fuites mémoire et des bugs de restauration de fragments.
onCleared() est appelé après onDestroy de l'Activity ou du Fragment, quand le ViewModel n'est plus nécessaire. Lors de la rotation d'écran, onCleared() n'est pas appelé — ViewModel survit à onDestroy. Ordre : onDestroy de Activity/Fragment → (ViewModelStore est nettoyé) → onCleared().
Techniquement oui, mais ce n'est pas recommandé. L'Activity est immédiatement détruite après onDestroy, et le Service démarré reste sans contrôle. Pour les tâches d'arrière-plan, utilisez WorkManager avec un délai : WorkManager garantit l'exécution même après la fin de l'Activity et survit à la mort du processus.
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