onDestroy : qu'est-ce que c'est, fin du travail d'Activity dans Android

Auteur : IT Sectr Publié le : 2026-03-04 Temps de lecture : 8 min

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 — le dernier appel avant la destruction d'une Activity ou d'un Fragment, destiné au nettoyage final des ressources.
  • L'appel à onDestroy n'est pas garanti lors de la mort du processus par le système — ne comptez pas sur lui pour sauvegarder des données critiques.
  • Dans onDestroy, vous devez annuler les tâches d'arrière-plan, fermer les sockets et les bases de données, et nettoyer le ViewModelStore.
  • Différence avec onStop : onStop — perte de visibilité (l'Activity reste en mémoire), onDestroy — destruction complète.
  • isFinishing() dans onDestroy montre si l'Activity se termine par commande utilisateur (finish()) ou par décision du système.

onDestroy : qu'est-ce que c'est dans Android ?

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 :

  • Appel explicite à finish() — l'utilisateur a appuyé sur « Retour » ou le développeur a appelé finishActivity().
  • Rotation d'écran — l'Activity est détruite et recréée avec une nouvelle configuration.
  • Changement de configuration — clavier, changement de langue, changement de taille d'écran (multi-fenêtre).
  • Décision du système — Android tue l'Activity pour libérer des ressources (mais onDestroy peut ne pas être appelé).

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).

Quand onDestroy est appelé — et quand il ne l'est pas

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é :

  • L'utilisateur appuie sur le bouton « Retour » — Activity.finish() → onPause → onStop → onDestroy.
  • Rotation d'écran — l'Activity est détruite (onPause → onStop → onDestroy), puis recréée.
  • Changement de configuration — paramètre système nécessitant la recréation de l'Activity.
  • Appel à finishAffinity() — termine toutes les Activities dans la pile.
  • Suppression d'un Fragment du FragmentManager — le Fragment reçoit onPause → onStop → onDestroyView → onDestroy → onDetach.

Quand onDestroy N'EST PAS appelé :

  • Mort du processus par le système — Android tue tout le processus de l'application quand la mémoire est insuffisante. L'Activity ne reçoit pas onDestroy car le processus se termine au niveau du noyau Linux.
  • Terminaison anormale — une exception non capturée dans le thread principal tue l'application sans appeler onDestroy.
  • Arrêt forcé — l'utilisateur arrête de force l'application dans les paramètres.

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 dans Activity et Fragment : points communs et différences

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).

ComposantMéthodes de destructionOrdreViewModel survit
ActivityonDestroyonPause → onStop → onDestroyNon (seulement si ViewModelStore n'est pas sauvegardé)
FragmentonDestroyView, onDestroy, onDetachonPause → onStop → onDestroyView → onDestroy → onDetachOui, 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.

Que faire dans onDestroy : liste de vérification de nettoyage

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 :

  • Annuler les coroutines et Flow — annulez les jobs qui ne sont pas liés à viewModelScope. viewModelScope est annulé automatiquement, mais lifecycleScope est lié au cycle de vie de l'Activity.
  • Fermer les sockets et canaux — WebSocket (OkHttp), BluetoothSocket, ServerSocket. Les garder ouverts après la destruction est une fuite de ressources système.
  • Fermer les fichiers et flux — FileInputStream, FileOutputStream, Cursor. Un Cursor peut provoquer ANR sur ContentProvider s'il n'est pas fermé.
  • Se désabonner de ContentObserver — si l'Activity surveille les changements de contenu (contacts, bibliothèque multimédia).
  • Désenregistrer BroadcastReceiver — les récepteurs enregistrés dynamiquement doivent être annulés.
  • Fermer la base de données — Room ferme la connexion automatiquement lorsque l'Application est détruite, mais SQLiteDatabase direct nécessite close() manuel.

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.

onDestroy et ViewModel : travail conjoint

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 :

  • Activity : onPause → onStop → onDestroy (Activity détruite).
  • ViewModel : NON détruit — le ViewModelStore est sauvegardé et transmis à la nouvelle Activity.
  • Nouvelle Activity : onCreate → onStart → onResume, reçoit le même ViewModel.

Lors de finish() (l'utilisateur a appuyé sur « Retour ») :

  • Activity : onPause → onStop → onDestroy.
  • ViewModel : onCleared() — appelé après onDestroy de l'Activity.
  • Toutes les coroutines de viewModelScope sont annulées automatiquement.

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.

Exemples de code avec onDestroy en Kotlin

Exemple 1 : onDestroy Activity avec annulation de coroutine lifecycleScope

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.

kotlin
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.

Exemple 2 : onDestroy Fragment avec nettoyage des références de View

Un Fragment nettoie correctement les références de View dans onDestroyView, empêchant les fuites mémoire dues aux fermetures.

kotlin
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.

Exemple 3 : Vérification de isFinishing dans onDestroy

Utiliser isFinishing() permet de distinguer si l'Activity se termine par commande utilisateur ou pour recréation.

kotlin
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

Est-ce que onDestroy peut ne pas être appelé ?

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.

Quelle est la différence entre onDestroy et finish() ?

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.

Dois-je appeler super.onDestroy() dans Fragment ?

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.

Quand onCleared() est-il appelé dans ViewModel par rapport à onDestroy ?

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().

Puis-je démarrer un Service depuis onDestroy ?

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é

  • onDestroy — le callback final du cycle de vie d'Activity et de Fragment, appelé avant la destruction complète du composant.
  • L'appel à onDestroy n'est pas garanti lors de la mort du processus — environ 5 — 8 % des terminaisons se produisent sans lui.
  • Dans onDestroy, vous devez libérer : callbacks réseau, sockets, flux de fichiers, BroadcastReceiver, ContentObserver.
  • ViewModel.onCleared() est appelé après onDestroy de l'Activity — viewModelScope est annulé automatiquement.
  • onDestroyView dans Fragment (séparé d'onDestroy) — l'endroit approprié pour nullifier les références de View.
  • Vérifier isFinishing() dans onDestroy permet de distinguer la terminaison par finish() de la recréation due aux changements de configuration.
  • Ne comptez pas sur onDestroy pour sauvegarder des données — utilisez onPause ou onSaveInstanceState.

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.

Discuter du projet

Lisez aussi