onDestroy — az Activity és Fragment életciklusának végső metódusa Androidban, amely a komponens teljes megsemmisítése előtt hívódik meg. Az onDestroy jelzi, hogy az Activity vagy Fragment befejezi a munkáját: minden erőforrást fel kell szabadítani, a beágyazott fragmenseket — meg kell semmisíteni, a ViewModel-t — ki kell tisztítani. A Google adatai szerint az onDestroy az Activity befejezésének 100%-ában meghívódik, de a folyamat megszakításakor (process death) a rendszer teljesen kihagyhatja az onDestroy meghívását. Az Android onDestroy dokumentációja hangsúlyozza, hogy ez a metódus nem garantálja a meghívást vészhelyzet esetén.
Főbb pontok
onDestroy — egy visszahívási metódus, amelyet az Android hív meg, mielőtt véglegesen megsemmisíti az Activity-t vagy Fragment-et. Ez az utolsó lehetőség a fejlesztő számára, hogy felszabadítsa az erőforrásokat, leállítsa a háttérműveleteket és befejezze az adatokkal való munkát. Az onDestroy végrehajtása után az Activity/Fragment példány megjelölésre kerül a szemétgyűjtő (GC) számára, és többé nem használható.
Az onDestroy meghívásának okai:
A Google Android Vitals (2025) statisztikái szerint az Activity megsemmisítések körülbelül 12%-a képernyőelforgatásból, 65%-a finish()-ből és 23%-a konfigurációváltozásból ered. A folyamatmegszakítások aránya az onDestroy kihagyásával körülbelül 5–8% a kis RAM-mal (4 GB alatt) rendelkező eszközöktől függően.
Az onDestroy a legtöbb szabványos forgatókönyvben meghívódik, de vannak fontos kivételek, amelyeket a fejlesztőnek figyelembe kell vennie. Az onDestroy meghívási garanciáinak megértése kritikus fontosságú az alkalmazás architektúrája szempontjából, különösen az adatok mentése és a WorkManager-feladatok leállítása terén.
Mikor hívódik meg az onDestroy:
Mikor NEM hívódik meg az onDestroy:
Az onDestroy meghívási garanciájának hiánya miatt a Google azt javasolja: soha ne támaszkodjon az onDestroy-ra kritikus adatok mentéséhez. Használja az onSaveInstanceState()-t, WorkManager-t vagy Room-ot automatikus mentéssel. Az onDestroy — az erőforrások felszabadítására szolgál, nem az adatok perzisztenciájára.
Az onDestroy mind az Activity, mind a Fragment számára létezik, de különböző szerződésekkel. A Fragment életciklusa részletesebb: az onDestroy mellett létezik onDestroyView (a View hierarchia megsemmisítése) és onDetach (leválasztás az Activity-ről).
| Komponens | Megsemmisítési metódusok | Sorrend | ViewModel túléli |
|---|---|---|---|
| Activity | onDestroy | onPause → onStop → onDestroy | Nem (csak ha a ViewModelStore nincs elmentve) |
| Fragment | onDestroyView, onDestroy, onDetach | onPause → onStop → onDestroyView → onDestroy → onDetach | Igen, ha a Fragment nincs eltávolítva |
A legfontosabb különbség: a Fragment esetében a View gyakrabban jön létre újra, mint maga a Fragment. Képernyőelforgatáskor a Fragment átesik az onDestroyView-n (View megsemmisítése), de maga a Fragment és annak ViewModel-je életben marad. Az onDestroyView — a megfelelő hely a View-ra mutató referenciák tisztítására a memóriaszivárgás elkerülése érdekében. A Fragment onDestroy-je — az Activity onDestroy-jének analógiája, a Fragment teljes eltávolításakor hívódik meg.
A beágyazott fragmentek (child fragments) a szülő Fragment onDestroy-je előtt semmisülnek meg. Az Activity-ben a gyermek fragmentek az onDestroy hívásakor kapnak onDestroy-t a szülő Activity-től. A sorrend garantált: a fragmentek korábban fejeződnek be, mint az őket tartalmazó Activity.
Az onDestroy az összes olyan erőforrás felszabadítására szolgál, amelyek nem élhetnek tovább az Activity-nél vagy Fragment-nél. Ellentétben az onStop-pal, amely az erőforrásokat a visszatérésig szabadítja fel, az onDestroy végleges tisztítást végez.
Kötelező műveletek ellenőrzőlistája az onDestroy-ben:
Mit NE tegyünk az onDestroy-ben: Ne mentsen adatokat az onDestroy-ben — használja az onPause-t vagy onSaveInstanceState-t. Ne indítson új Service-t vagy WorkManager-feladatot — az Activity megsemmisül, és nem tudja nyomon követni az eredményt. Ne próbálja frissíteni a UI-t — a View hierarchia már megsemmisült vagy megsemmisítés alatt áll; a findViewById() hívása null-t ad vissza.
A ViewModel úgy lett tervezve, hogy túlélje az Activity onDestroy-jét képernyőelforgatáskor, de finish()-kor az Activity-vel együtt megsemmisüljön. Ez az aszimmetrikus viselkedés — a fejlesztők körében a zavar fő oka.
Képernyőelforgatáskor:
finish()-kor (a felhasználó megnyomta a „Vissza" gombot):
Tehát a viewModelScope leállítása az onDestroy-ben nem szükséges — a ViewModel ezt magától megteszi. Ha a lifecycleScope-ot használja (amely az Activity-hez kapcsolódik, nem a ViewModel-hez), állítsa le az onDestroy-ben a lifecycleScope.cancel() segítségével, vagy kezelje a Job-ot manuálisan.
Bemutatja a lifecycleScope helyes kezelését Activity-ben: a coroutine elindul a hálózati állapot figyelésére és leáll az onDestroy-ben.
class NetworkMonitorActivity : AppCompatActivity() {
private val networkCallback = object : ConnectivityManager.NetworkCallback() {
override fun onAvailable(network: Network) {
Log.d("NetworkMonitor", "Hálózat elérhető")
}
override fun onLost(network: Network) {
Log.d("NetworkMonitor", "Hálózat elveszett")
}
}
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", "Hálózatfigyelés elindítva")
}
}
override fun onDestroy() {
super.onDestroy()
val connectivityManager = getSystemService(ConnectivityManager::class.java)
connectivityManager.unregisterNetworkCallback(networkCallback)
Log.d("NetworkMonitor", "onDestroy: callback leállítva")
}
}
Az onDestroy-ben a hálózati callback regisztrációja leáll. A lifecycleScope automatikusan leáll az életciklus megsemmisülésekor — a coroutine külön leállítása nem szükséges. A hálózati callback-et feltétlenül le kell iratkozni, különben a rendszerben marad az Activity megsemmisítése után is.
A Fragment helyesen tisztítja a View referenciákat az onDestroyView-ben, megelőzve a lezárások által okozott memóriaszivárgást.
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 teljesen megsemmisült")
}
}
Az onDestroyView-ben a View referenciák nullára állítódnak — ez megakadályozza a memóriaszivárgást, ha az imageLoader-ben lévő lezárás megtart egy referenciát az avatarView-ra. Maga a Fragment és annak ViewModel-je életben maradnak az onDestroy-ig. Az imageLoader.cancel() leállítja a betöltést, ha a Fragment elhagyja a képernyőt.
Az isFinishing() használata lehetővé teszi annak megkülönböztetését, hogy az Activity a felhasználó parancsára vagy újralétrehozás céljából fejeződik be.
class AnalyticsActivity : AppCompatActivity() {
private val analytics = Analytics()
override fun onDestroy() {
if (isFinishing) {
Log.d("AnalyticsActivity", "Activity finish()-sel fejeződik be — analitikát küldünk")
analytics.sendSessionEnd()
} else {
Log.d("AnalyticsActivity", "Activity újralétrehozva (forgatás/konfiguráció) — nem küldünk analitikát")
}
super.onDestroy()
}
}
Az isFinishing() ellenőrzése — fontos minta analitikához, naplózáshoz és munkamenet-adatok tisztításához. Elforgatáskor nem kell munkamenet-befejezési eseményeket küldeni — a felhasználó még mindig az alkalmazással dolgozik. A Google Analytics szerint az isFinishing() helytelen ellenőrzése a 40%-át teszi ki a hamis munkamenet-eseményeknek.
Gyakran Ismételt Kérdések
Igen, lehetséges — a rendszer általi folyamatmegszakításkor (process death), a felhasználó általi Force Stop-kor vagy vészhelyzeti befejezéskor. A Google adatai szerint az Activity befejezések körülbelül 5–8%-a az onDestroy meghívása nélkül történik. A fejlesztő nem támaszkodhat az onDestroy-ra kritikus adatok mentéséhez — használja az onPause-t vagy onSaveInstanceState-t.
finish() — az Activity megsemmisítését elindító hívás. onDestroy — a visszahívás, amely a finish() végrehajtása során hívódik meg. A finish() kötelező az onDestroy meghívásához normál befejezéskor. A finish()-t a rendszer vagy a fejlesztő hívhatja meg, az onDestroy — csak rendszer-visszahívás.
Igen, feltétlenül mind az Activity-ben, mind a Fragment-ben. A super.onDestroy() biztosítja a ChildFragmentManager, LoaderManager és más rendszerkomponensek megfelelő tisztítását. A super.onDestroy() kihagyása memóriaszivárgáshoz és hibákhoz vezet a fragmentek visszaállításakor.
Az onCleared() az Activity vagy Fragment onDestroy-je után hívódik meg, amikor a ViewModel már nem szükséges. Képernyőelforgatáskor az onCleared() nem hívódik meg — a ViewModel túléli az onDestroy-t. Sorrend: onDestroy Activity/Fragment → (ViewModelStore tisztítása) → onCleared().
Technikailag igen, de nem ajánlott. Az Activity az onDestroy után azonnal megsemmisül, és az elindított Service kontroll nélkül marad. Háttérfeladatokhoz használjon WorkManager-t késleltetéssel: a WorkManager garantálja a végrehajtást az Activity befejezése után is, és túléli a process death-et.
Összegzés
Kulcsrakész mobilalkalmazást fejlesztünk
Az IT Sectr 2017 óta készít iOS és Android alkalmazásokat induló vállalkozásoknak és vállalkozásoknak. Tanácsot adunk, és a legjobb megoldást javasoljuk.
Olvassa el is