onDestroy: wat is het, beëindigen van Activity in Android

Auteur: IT Sectr Gepubliceerd: 2026-03-04 Leestijd: 8 min

onDestroy — de laatste methode van de levenscyclus van Activity en Fragment in Android, aangeroepen vóór de volledige vernietiging van de component. onDestroy geeft aan dat Activity of Fragment zijn werk beëindigt: alle bronnen moeten worden vrijgemaakt, geneste fragmenten — vernietigd, ViewModel — opgeschoond. Volgens Google-gegevens wordt onDestroy in 100% van de gevallen van beëindiging van Activity aangeroepen, maar bij het doden van een proces (process death) kan het systeem de aanroep van onDestroy volledig overslaan. Android-documentatie over onDestroy benadrukt dat deze methode geen aanroep garandeert bij een noodstop.

Belangrijkste

  • onDestroy — de laatste aanroep vóór het vernietigen van Activity of Fragment, bedoeld voor het definitief opschonen van bronnen.
  • De aanroep van onDestroy is niet gegarandeerd bij het doden van een proces door het systeem (process death) — vertrouw er niet op voor het opslaan van kritieke gegevens.
  • In onDestroy moeten achtergrondtaken worden geannuleerd, sockets en databases worden gesloten, ViewModelStore worden opgeschoond.
  • Verschil met onStop: onStop — verlies van zichtbaarheid (Activity leeft in het geheugen), onDestroy — volledige vernietiging.
  • isFinishing() in onDestroy toont of Activity wordt beëindigd op gebruikerscommando (finish()) of op systeembeslissing.

onDestroy: wat is het in Android?

onDestroy — een callback-methode die Android aanroept voordat het Activity of Fragment definitief vernietigt. Dit is de laatste kans voor de ontwikkelaar om bronnen vrij te maken, achtergrondbewerkingen te annuleren en het werk met gegevens te beëindigen. Na uitvoering van onDestroy wordt de instantie Activity/Fragment gemarkeerd voor garbage collection (GC) en kan niet meer worden gebruikt.

Redenen voor het aanroepen van onDestroy:

  • Expliciete aanroep van finish() — de gebruiker heeft op „Terug" gedrukt of de ontwikkelaar heeft finishActivity() aangeroepen.
  • Schermrotatie — Activity wordt vernietigd en opnieuw gemaakt met een nieuwe configuratie.
  • Configuratiewijziging — toetsenbord, taalwijziging, wijziging van schermgrootte (multi-window).
  • Systeembeslissing — Android vernietigt Activity om bronnen vrij te maken (maar onDestroy wordt mogelijk niet aangeroepen).

Volgens Google Android Vitals-statistieken (2025) is ongeveer 12% van alle gevallen van vernietiging van Activity te wijten aan schermrotatie, 65% aan finish() en 23% aan configuratiewijziging. Het percentage procesdodingen met overslaan van onDestroy is ongeveer 5–8%, afhankelijk van apparaten met weinig RAM (minder dan 4 GB).

Wanneer onDestroy wordt aangeroepen — en wanneer niet

onDestroy wordt in de meeste standaardsituaties aangeroepen, maar er zijn belangrijke uitzonderingen waar de ontwikkelaar rekening mee moet houden. Inzicht in de garanties van de aanroep van onDestroy is cruciaal voor de architectuur van de applicatie, met name voor het opslaan van gegevens en het annuleren van WorkManager-taken.

Wanneer onDestroy wordt aangeroepen:

  • De gebruiker drukt op de knop „Terug" — Activity.finish() → onPause → onStop → onDestroy.
  • Schermrotatie — Activity wordt vernietigd (onPause → onStop → onDestroy), vervolgens opnieuw gemaakt.
  • Configuratiewijziging — systeeminstelling die het opnieuw maken van Activity vereist.
  • Aanroep van finishAffinity() — beëindigen van alle Activity in de stack.
  • Verwijderen van Fragment uit FragmentManager — Fragment ontvangt onPause → onStop → onDestroyView → onDestroy → onDetach.

Wanneer onDestroy NIET wordt aangeroepen:

  • Procesdoding door het systeem (process death) — Android doodt het hele proces van de applicatie bij geheugengebrek. Activity ontvangt geen onDestroy omdat het proces op Linux-kernelniveau wordt beëindigd.
  • Noodstop — een niet-afgevangen uitzondering in de hoofdthread doodt de applicatie zonder aanroep van onDestroy.
  • Force Stop — de gebruiker stopt de applicatie geforceerd in de instellingen.

Vanwege het ontbreken van een garantie voor de aanroep van onDestroy beveelt Google aan: vertrouw nooit op onDestroy voor het opslaan van kritieke gegevens. Gebruik onSaveInstanceState(), WorkManager of Room met automatisch opslaan. onDestroy — voor het vrijmaken van bronnen, niet voor persistentie.

onDestroy in Activity en Fragment: overeenkomsten en verschillen

onDestroy bestaat zowel voor Activity als voor Fragment, maar met verschillende contracten. Bij Fragment is de levenscyclus gedetailleerder: naast onDestroy zijn er onDestroyView (vernietiging van de View-hiërarchie) en onDetach (loskoppeling van Activity).

ComponentVernietigingsmethodenVolgordeViewModel overleeft
ActivityonDestroyonPause → onStop → onDestroyNee (alleen als ViewModelStore niet is opgeslagen)
FragmentonDestroyView, onDestroy, onDetachonPause → onStop → onDestroyView → onDestroy → onDetachJa, als Fragment niet is verwijderd

Het belangrijkste verschil: bij Fragment wordt View vaker opnieuw gemaakt dan het Fragment zelf. Bij schermrotatie doorloopt Fragment onDestroyView (vernietiging van View), maar het Fragment zelf en zijn ViewModel blijven leven. onDestroyView — de juiste plaats voor het opschonen van verwijzingen naar View om geheugenlekken te voorkomen. onDestroy van Fragment — analoog aan onDestroy van Activity, aangeroepen bij volledige verwijdering van Fragment.

Geneste fragmenten (child fragments) worden vernietigd vóór onDestroy van het bovenliggende Fragment. In Activity ontvangen onderliggende fragmenten onDestroy bij het aanroepen van onDestroy van het bovenliggende Activity. De volgorde is gegarandeerd: fragmenten eindigen eerder dan het Activity dat ze bevat.

Wat te doen in onDestroy: opruimchecklist

onDestroy is bedoeld voor het vrijmaken van alle bronnen die niet langer mogen leven dan Activity of Fragment. In tegenstelling tot onStop, dat bronnen vrijmaakt tot de terugkeer, voert onDestroy de definitieve opschoning uit.

Checklist van verplichte acties in onDestroy:

  • Annuleren van coroutines en Flow — annuleer jobs die niet zijn gekoppeld aan viewModelScope. viewModelScope wordt automatisch geannuleerd, maar lifecycleScope is gekoppeld aan de levenscyclus van Activity.
  • Sluiten van sockets en kanalen — WebSocket (OkHttp), BluetoothSocket, ServerSocket. Ze open houden na vernietiging is een lek van systeembronnen.
  • Sluiten van bestanden en streams — FileInputStream, FileOutputStream, Cursor. Cursor kan ANR veroorzaken op ContentProvider als deze niet wordt gesloten.
  • Uitschrijven van ContentObserver — als Activity inhoudswijzigingen (contacten, mediatheek) volgt.
  • Uitschrijven van BroadcastReceiver — dynamisch geregistreerde receivers moeten worden geannuleerd.
  • Sluiten van de database — Room sluit de verbinding automatisch bij vernietiging van Application, maar directe SQLiteDatabase vereist handmatig close().

Wat NIET te doen in onDestroy: Sla geen gegevens op in onDestroy — gebruik onPause of onSaveInstanceState. Start geen nieuwe Service of WorkManager-taken — Activity wordt vernietigd en u kunt het resultaat niet volgen. Probeer de UI niet bij te werken — de View-hiërarchie is al vernietigd of in het proces van vernietiging; aanroep van findViewById() retourneert null.

onDestroy en ViewModel: samenwerking

ViewModel is ontworpen om onDestroy van Activity te overleven bij schermrotatie, maar samen met Activity te worden vernietigd bij finish(). Dit asymmetrische gedrag — de belangrijkste oorzaak van verwarring bij ontwikkelaars.

Bij schermrotatie:

  • Activity: onPause → onStop → onDestroy (Activity vernietigd).
  • ViewModel: NIET vernietigd — ViewModelStore wordt bewaard en doorgegeven aan het nieuwe Activity.
  • Nieuw Activity: onCreate → onStart → onResume, ontvangt dezelfde ViewModel.

Bij finish() (gebruiker heeft op „Terug" gedrukt):

  • Activity: onPause → onStop → onDestroy.
  • ViewModel: onCleared() — aangeroepen na onDestroy van Activity.
  • Alle coroutines van viewModelScope worden automatisch geannuleerd.

Het annuleren van viewModelScope in onDestroy is dus niet nodig — ViewModel doet dit zelf. Als u lifecycleScope (gebonden aan Activity, niet aan ViewModel) gebruikt, annuleer deze dan in onDestroy via lifecycleScope.cancel() of beheer Job handmatig.

Codevoorbeelden met onDestroy in Kotlin

Voorbeeld 1: onDestroy Activity met annuleren van lifecycleScope-coroutine

Demonstreert correct beheer van lifecycleScope in Activity: de coroutine wordt gestart voor het volgen van de netwerkstatus en geannuleerd in onDestroy.

kotlin
class NetworkMonitorActivity : AppCompatActivity() {
    private val networkCallback = object : ConnectivityManager.NetworkCallback() {
        override fun onAvailable(network: Network) {
            Log.d("NetworkMonitor", "Netwerk beschikbaar")
        }
        override fun onLost(network: Network) {
            Log.d("NetworkMonitor", "Netwerk verloren")
        }
    }

    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", "Netwerkmonitoring gestart")
        }
    }

    override fun onDestroy() {
        super.onDestroy()
        val connectivityManager = getSystemService(ConnectivityManager::class.java)
        connectivityManager.unregisterNetworkCallback(networkCallback)
        Log.d("NetworkMonitor", "onDestroy: callback geannuleerd")
    }
}

In onDestroy wordt de registratie van de netwerk-callback geannuleerd. lifecycleScope wordt automatisch geannuleerd bij vernietiging van de levenscyclus — afzonderlijk annuleren van de coroutine is niet nodig. De netwerk-callback moet verplicht worden uitgeschreven, anders blijft deze in het systeem hangen, zelfs na vernietiging van Activity.

Voorbeeld 2: onDestroy Fragment met opschonen van View-verwijzingen

Fragment ruimt correct verwijzingen naar View op in onDestroyView, waardoor geheugenlekken veroorzaakt door closures worden voorkomen.

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 volledig vernietigd")
    }
}

In onDestroyView worden verwijzingen naar View op nul gezet — dit voorkomt geheugenlekken als de closure in imageLoader een verwijzing naar avatarView vasthoudt. Het Fragment zelf en zijn ViewModel blijven leven tot onDestroy. imageLoader.cancel() annuleert het laden als Fragment het scherm verlaat.

Voorbeeld 3: Controleren van isFinishing in onDestroy

Het gebruik van isFinishing() maakt het mogelijk te onderscheiden of Activity wordt beëindigd op gebruikerscommando of voor opnieuw maken.

kotlin
class AnalyticsActivity : AppCompatActivity() {
    private val analytics = Analytics()

    override fun onDestroy() {
        if (isFinishing) {
            Log.d("AnalyticsActivity", "Activity eindigt met finish() — analytics verzenden")
            analytics.sendSessionEnd()
        } else {
            Log.d("AnalyticsActivity", "Activity wordt opnieuw gemaakt (rotatie/configuratie) — geen analytics verzenden")
        }
        super.onDestroy()
    }
}

Het controleren van isFinishing() — een belangrijk patroon voor analytics, logging en opschonen van sessiegegevens. Bij rotatie hoeven geen sessie-eindegebeurtenissen te worden verzonden — de gebruiker werkt nog steeds met de applicatie. Volgens Google Analytics is onjuiste controle van isFinishing() de oorzaak van 40% van de valse sessiegebeurtenissen.

Veelgestelde vragen

Kan onDestroy niet worden aangeroepen?

Ja, dat kan — bij procesdoding door het systeem (process death), Force Stop door de gebruiker of noodstop. Volgens Google-gegevens vindt ongeveer 5–8% van de beëindigingen van Activity plaats zonder aanroep van onDestroy. De ontwikkelaar moet niet vertrouwen op onDestroy voor het opslaan van kritieke gegevens — gebruik onPause of onSaveInstanceState.

Wat is het verschil tussen onDestroy en finish()?

finish() — de aanroep die de vernietiging van Activity initieert. onDestroy — de callback die wordt aangeroepen tijdens de uitvoering van finish(). finish() is verplicht voor het aanroepen van onDestroy bij normale beëindiging. finish() kan worden aangeroepen door het systeem of de ontwikkelaar, onDestroy — alleen een systeem-callback.

Moet super.onDestroy() worden aangeroepen in Fragment?

Ja, absoluut zowel in Activity als in Fragment. super.onDestroy() zorgt voor correcte opschoning van ChildFragmentManager, LoaderManager en andere systeemcomponenten. Het overslaan van super.onDestroy() leidt tot geheugenlekken en fouten bij het herstellen van fragmenten.

Wanneer wordt onCleared() bij ViewModel aangeroepen ten opzichte van onDestroy?

onCleared() wordt aangeroepen na onDestroy van Activity of Fragment, wanneer ViewModel niet meer nodig is. Bij schermrotatie wordt onCleared() niet aangeroepen — ViewModel overleeft onDestroy. Volgorde: onDestroy Activity/Fragment → (ViewModelStore wordt opgeschoond) → onCleared().

Kan een Service worden gestart vanuit onDestroy?

Technisch ja, maar het wordt niet aanbevolen. Activity wordt onmiddellijk na onDestroy vernietigd en de gestarte Service blijft zonder controle. Gebruik voor achtergrondtaken WorkManager met vertraging: WorkManager garandeert uitvoering zelfs na beëindiging van Activity en overleeft process death.

Samenvatting

  • onDestroy — de laatste callback van de levenscyclus van Activity en Fragment, aangeroepen vóór volledige vernietiging van de component.
  • De aanroep van onDestroy is niet gegarandeerd bij process death — ongeveer 5–8% van de beëindigingen vindt plaats zonder.
  • In onDestroy moeten worden vrijgemaakt: netwerk-callbacks, sockets, bestandsstreams, BroadcastReceiver, ContentObserver.
  • ViewModel.onCleared() wordt aangeroepen na onDestroy van Activity — viewModelScope wordt automatisch geannuleerd.
  • onDestroyView bij Fragment (apart van onDestroy) — de juiste plaats voor het op nul zetten van verwijzingen naar View.
  • Controle van isFinishing() in onDestroy maakt het mogelijk onderscheid te maken tussen beëindiging door finish() en opnieuw maken bij configuratiewijzigingen.
  • Vertrouw niet op onDestroy voor het opslaan van gegevens — gebruik onPause of onSaveInstanceState.

We ontwikkelen een mobiele applicatie turnkey

IT Sectr creëert sinds 2017 iOS- en Android-applicaties voor startups en bedrijven. We adviseren u en stellen de beste oplossing voor.

Bespreek het project

Lees ook