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 — 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:
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).
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:
Wanneer onDestroy NIET wordt aangeroepen:
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 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).
| Component | Vernietigingsmethoden | Volgorde | ViewModel overleeft |
|---|---|---|---|
| Activity | onDestroy | onPause → onStop → onDestroy | Nee (alleen als ViewModelStore niet is opgeslagen) |
| Fragment | onDestroyView, onDestroy, onDetach | onPause → onStop → onDestroyView → onDestroy → onDetach | Ja, 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.
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:
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.
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:
Bij finish() (gebruiker heeft op „Terug" gedrukt):
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.
Demonstreert correct beheer van lifecycleScope in Activity: de coroutine wordt gestart voor het volgen van de netwerkstatus en geannuleerd in onDestroy.
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.
Fragment ruimt correct verwijzingen naar View op in onDestroyView, waardoor geheugenlekken veroorzaakt door closures worden voorkomen.
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.
Het gebruik van isFinishing() maakt het mogelijk te onderscheiden of Activity wordt beëindigd op gebruikerscommando of voor opnieuw maken.
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
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.
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.
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.
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().
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
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.
Lees ook