onDestroy: ano ito, pagtatapos ng Activity sa Android

May-akda: IT Sectr Nai-publish: 2026-03-04 Oras ng pagbabasa: 8 min

onDestroy — ang huling paraan ng lifecycle ng Activity at Fragment sa Android, na tinatawag bago ang kumpletong pagwasak ng component. Ang onDestroy ay nagpapahiwatig na ang Activity o Fragment ay nagtatapos ng trabaho nito: lahat ng resources ay dapat palayain, nested fragments — wasakin, ViewModel — linisin. Ayon sa data ng Google, ang onDestroy ay tinatawag sa 100% ng mga kaso ng pagtatapos ng Activity, ngunit sa pagpatay ng proseso (process death) maaaring laktawan ng system ang pagtawag sa onDestroy nang buo. Dokumentasyon ng Android tungkol sa onDestroy ay nagbibigay-diin na ang pamamaraang ito ay hindi garantiya ng pagtawag sa emergency na pagtatapos.

Mga Pangunahing Punto

  • onDestroy — huling tawag bago wasakin ang Activity o Fragment, para sa huling paglilinis ng resources.
  • Ang pagtawag sa onDestroy ay hindi garantisado kapag pinatay ng system ang proseso (process death) — huwag umasa dito para sa pag-save ng kritikal na data.
  • Sa onDestroy kailangang kanselahin ang mga background task, isara ang sockets at database, linisin ang ViewModelStore.
  • Pagkakaiba mula sa onStop: onStop — pagkawala ng visibility (Activity buhay sa memorya), onDestroy — kumpletong pagwasak.
  • Ang isFinishing() sa onDestroy ay nagpapakita kung ang Activity ay nagtatapos sa utos ng user (finish()) o sa desisyon ng system.

onDestroy: ano ito sa Android?

onDestroy — isang callback method na tinatawag ng Android bago tuluyang wasakin ang Activity o Fragment. Ito ang huling pagkakataon para sa developer na palayain ang resources, kanselahin ang mga background operation, at tapusin ang trabaho gamit ang data. Pagkatapos ng execution ng onDestroy, ang instance ng Activity/Fragment ay minarkahan para sa garbage collection (GC) at hindi na magagamit.

Mga dahilan ng pagtawag sa onDestroy:

  • Eksplisitong tawag ng finish() — pinindot ng user ang "Bumalik" o tinawag ng developer ang finishActivity().
  • Pag-ikot ng screen — ang Activity ay winawasak at nilikhang muli gamit ang bagong configuration.
  • Pagbabago ng configuration — keyboard, pagbabago ng wika, pagbabago ng laki ng screen (multi-window).
  • Desisyon ng system — pinapatay ng Android ang Activity para palayain ang resources (ngunit maaaring hindi tawagin ang onDestroy).

Ayon sa statistics ng Google Android Vitals (2025), humigit-kumulang 12% ng lahat ng kaso ng pagwasak ng Activity ay dahil sa pag-ikot ng screen, 65% dahil sa finish() at 23% dahil sa pagbabago ng configuration. Ang porsyento ng pagpatay ng proseso na may paglaktaw sa onDestroy ay humigit-kumulang 5–8% depende sa device na may maliit na RAM (mas mababa sa 4 GB).

Kailan tinatawag ang onDestroy — at kailan hindi

Ang onDestroy ay tinatawag sa karamihan ng mga standard na sitwasyon, ngunit may mahahalagang eksepsyon na dapat isaalang-alang ng developer. Ang pag-unawa sa mga garantiya ng pagtawag sa onDestroy ay kritikal para sa arkitektura ng application, lalo na para sa pag-save ng data at pagkansela ng mga WorkManager task.

Kailan tinatawag ang onDestroy:

  • Pinindot ng user ang button na "Bumalik" — Activity.finish() → onPause → onStop → onDestroy.
  • Pag-ikot ng screen — ang Activity ay winawasak (onPause → onStop → onDestroy), pagkatapos ay nilikhang muli.
  • Pagbabago ng configuration — setting ng system na nangangailangan ng muling paglikha ng Activity.
  • Tawag ng finishAffinity() — pagtatapos ng lahat ng Activity sa stack.
  • Pag-alis ng Fragment mula sa FragmentManager — Fragment ay tumatanggap ng onPause → onStop → onDestroyView → onDestroy → onDetach.

Kailan HINDI tinatawag ang onDestroy:

  • Pagpatay ng proseso ng system (process death) — pinapatay ng Android ang buong proseso ng application kapag kulang ang memorya. Hindi natatanggap ng Activity ang onDestroy dahil ang proseso ay tinatapos sa antas ng Linux kernel.
  • Emergency na pagtatapos — isang hindi nahuling exception sa main thread ay pumapatay ng application nang walang pagtawag sa onDestroy.
  • Force Stop — pinipilit ng user na ihinto ang application sa mga setting.

Dahil sa kawalan ng garantiya ng pagtawag sa onDestroy, inirerekomenda ng Google: huwag kailanman umasa sa onDestroy para sa pag-save ng kritikal na data. Gamitin ang onSaveInstanceState(), WorkManager, o Room na may automatic na pag-save. onDestroy — para sa pagpapalaya ng resources, hindi para sa persistence.

onDestroy sa Activity at Fragment: pagkakatulad at pagkakaiba

Ang onDestroy ay umiiral para sa parehong Activity at Fragment, ngunit may magkaibang kontrata. Sa Fragment, ang lifecycle ay mas detalyado: bukod sa onDestroy mayroong onDestroyView (pagwasak ng View hierarchy) at onDetach (paghiwalay mula sa Activity).

ComponentMga paraan ng pagwasakPagkakasunod-sunodViewModel nakaligtas
ActivityonDestroyonPause → onStop → onDestroyHindi (kung hindi nai-save ang ViewModelStore)
FragmentonDestroyView, onDestroy, onDetachonPause → onStop → onDestroyView → onDestroy → onDetachOo, kung ang Fragment ay hindi inalis

Ang pangunahing pagkakaiba: sa Fragment, ang View ay mas madalas na nilikhang muli kaysa sa Fragment mismo. Sa pag-ikot ng screen, ang Fragment ay dumadaan sa onDestroyView (pagwasak ng View), ngunit ang Fragment mismo at ang ViewModel nito ay nananatiling buhay. onDestroyView — ang tamang lugar para linisin ang mga reference sa View upang maiwasan ang pagtagas ng memorya. onDestroy ng Fragment — kahalintulad ng onDestroy ng Activity, tinatawag kapag ganap na inalis ang Fragment.

Ang mga nested fragment (child fragments) ay winawasak bago ang onDestroy ng parent Fragment. Sa Activity, ang child fragments ay tumatanggap ng onDestroy kapag tinawag ang onDestroy ng parent Activity. Ang pagkakasunod-sunod ay garantisado: ang mga fragment ay natatapos nang mas maaga kaysa sa Activity na naglalaman ng mga ito.

Ano ang gagawin sa onDestroy: checklist ng paglilinis

Ang onDestroy ay para sa pagpapalaya ng lahat ng resources na hindi dapat mabuhay nang mas mahaba kaysa sa Activity o Fragment. Hindi tulad ng onStop na nagpapalaya ng resources hanggang sa pagbabalik, ang onDestroy ay nagsasagawa ng huling paglilinis.

Checklist ng mga ipinag-uutos na aksyon sa onDestroy:

  • Pagkansela ng coroutine at Flow — kanselahin ang mga job na hindi naka-ugnay sa viewModelScope. Ang viewModelScope ay awtomatikong kinakansela, ngunit ang lifecycleScope ay naka-ugnay sa lifecycle ng Activity.
  • Pagsasara ng sockets at channels — WebSocket (OkHttp), BluetoothSocket, ServerSocket. Ang pagpapanatiling bukas ng mga ito pagkatapos ng pagwasak ay pagtagas ng system resources.
  • Pagsasara ng mga file at stream — FileInputStream, FileOutputStream, Cursor. Ang Cursor ay maaaring magdulot ng ANR sa ContentProvider kung hindi sarado.
  • Pag-unsubscribe mula sa ContentObserver — kung sinusubaybayan ng Activity ang mga pagbabago sa content (contacts, media library).
  • Pag-unsubscribe mula sa BroadcastReceiver — ang mga dynamic na naka-rehistro na receiver ay dapat kanselahin.
  • Pagsasara ng database — awtomatikong isinasara ng Room ang koneksyon kapag winasak ang Application, ngunit ang direktang SQLiteDatabase ay nangangailangan ng manual na close().

Ano ang HINDI gagawin sa onDestroy: Huwag mag-save ng data sa onDestroy — gamitin ang onPause o onSaveInstanceState. Huwag magsimula ng bagong Service o WorkManager task — ang Activity ay wawasakin at hindi mo masusubaybayan ang resulta. Huwag subukang i-update ang UI — ang View hierarchy ay wasak na o nasa proseso ng pagwasak; ang pagtawag sa findViewById() ay magbabalik ng null.

onDestroy at ViewModel: pagtutulungan

Ang ViewModel ay dinisenyo upang mabuhay mula sa onDestroy ng Activity sa pag-ikot ng screen, ngunit mawasak kasama ng Activity sa finish(). Ang asimetrikong pag-uugali na ito — ang pangunahing dahilan ng pagkalito sa mga developer.

Sa pag-ikot ng screen:

  • Activity: onPause → onStop → onDestroy (Activity nawasak).
  • ViewModel: HINDI nawasak — ang ViewModelStore ay nai-save at ipinapasa sa bagong Activity.
  • Bagong Activity: onCreate → onStart → onResume, natatanggap ang parehong ViewModel.

Sa finish() (pinindot ng user ang "Bumalik"):

  • Activity: onPause → onStop → onDestroy.
  • ViewModel: onCleared() — tinatawag pagkatapos ng onDestroy ng Activity.
  • Lahat ng coroutine ng viewModelScope ay awtomatikong kinakansela.

Samakatuwid, ang pagkansela ng viewModelScope sa onDestroy ay hindi kinakailangan — ang ViewModel ang gagawa nito. Kung gumagamit ka ng lifecycleScope (naka-ugnay sa Activity, hindi sa ViewModel), kanselahin ito sa onDestroy sa pamamagitan ng lifecycleScope.cancel() o pamahalaan ang Job nang manu-mano.

Mga halimbawa ng code na may onDestroy sa Kotlin

Halimbawa 1: onDestroy Activity na may pagkansela ng lifecycleScope coroutine

Nagpapakita ng wastong pamamahala ng lifecycleScope sa Activity: ang coroutine ay sinimulan para sa pagsubaybay sa katayuan ng network at kinansela sa onDestroy.

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

    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", "Pagsubaybay sa network sinimulan")
        }
    }

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

Sa onDestroy, ang rehistrasyon ng network callback ay kinansela. Ang lifecycleScope ay awtomatikong kinakansela kapag winasak ang lifecycle — hindi kinakailangan ang hiwalay na pagkansela ng coroutine. Ang network callback ay dapat na naka-unsubscribe, kung hindi man ito ay mananatili sa system kahit pagkatapos ng pagwasak ng Activity.

Halimbawa 2: onDestroy Fragment na may paglilinis ng View references

Ang Fragment ay wastong naglilinis ng mga reference sa View sa onDestroyView, na pumipigil sa pagtagas ng memorya dulot ng mga closure.

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 ganap na nawasak")
    }
}

Sa onDestroyView, ang mga reference sa View ay nire-reset sa zero — ito ay pumipigil sa pagtagas ng memorya kung ang closure sa imageLoader ay humahawak ng reference sa avatarView. Ang Fragment mismo at ang ViewModel nito ay nananatiling buhay hanggang onDestroy. imageLoader.cancel() ay kinakansela ang pag-load kung ang Fragment ay umalis sa screen.

Halimbawa 3: Pagsusuri ng isFinishing sa onDestroy

Ang paggamit ng isFinishing() ay nagbibigay-daan upang makilala kung ang Activity ay nagtatapos sa utos ng user o para sa muling paglikha.

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

    override fun onDestroy() {
        if (isFinishing) {
            Log.d("AnalyticsActivity", "Activity nagtatapos sa finish() — nagpapadala ng analytics")
            analytics.sendSessionEnd()
        } else {
            Log.d("AnalyticsActivity", "Activity nilikhang muli (rotation/configuration) — hindi nagpapadala ng analytics")
        }
        super.onDestroy()
    }
}

Ang pagsusuri ng isFinishing() — mahalagang pattern para sa analytics, pag-log at paglilinis ng session data. Sa pag-ikot, hindi kailangang magpadala ng mga event ng pagtatapos ng session — ang user ay nagtatrabaho pa rin sa application. Ayon sa Google Analytics, ang maling pagsusuri ng isFinishing() ay sanhi ng 40% ng mga maling session event.

Mga Madalas Itanong

Maaari bang hindi tawagin ang onDestroy?

Oo, maaari — sa pagpatay ng proseso ng system (process death), Force Stop ng user o emergency na pagtatapos. Ayon sa data ng Google, humigit-kumulang 5–8% ng pagtatapos ng Activity ay nangyayari nang walang pagtawag sa onDestroy. Ang developer ay hindi dapat umasa sa onDestroy para sa pag-save ng kritikal na data — gamitin ang onPause o onSaveInstanceState.

Ano ang pagkakaiba ng onDestroy sa finish()?

finish() — ang tawag na nag-uumpisa ng pagwasak ng Activity. onDestroy — ang callback na tinatawag sa proseso ng execution ng finish(). Ang finish() ay kinakailangan para sa pagtawag ng onDestroy sa normal na pagtatapos. Ang finish() ay maaaring tawagin ng system o developer, ang onDestroy — callback lamang ng system.

Kailangan bang tawagin ang super.onDestroy() sa Fragment?

Oo, kinakailangan kapwa sa Activity at sa Fragment. Ang super.onDestroy() ay nagsisiguro ng wastong paglilinis ng ChildFragmentManager, LoaderManager at iba pang system component. Ang paglaktaw sa super.onDestroy() ay humahantong sa pagtagas ng memorya at mga bug sa pag-restore ng fragment.

Kailan tinatawag ang onCleared() sa ViewModel kaugnay ng onDestroy?

Ang onCleared() ay tinatawag pagkatapos ng onDestroy ng Activity o Fragment, kapag hindi na kailangan ang ViewModel. Sa pag-ikot ng screen, ang onCleared() ay hindi tinatawag — ang ViewModel ay nabubuhay mula sa onDestroy. Pagkakasunod-sunod: onDestroy Activity/Fragment → (ViewModelStore ay nililinis) → onCleared().

Maaari bang magsimula ng Service mula sa onDestroy?

Teknikal na oo, ngunit hindi inirerekomenda. Ang Activity ay agad na nawawasak pagkatapos ng onDestroy at ang sinimulang Service ay nananatiling walang kontrol. Para sa mga background task, gamitin ang WorkManager na may delay: ginagarantiyahan ng WorkManager ang execution kahit pagkatapos ng pagtatapos ng Activity at nabubuhay mula sa process death.

Konklusyon

  • onDestroy — ang huling callback ng lifecycle ng Activity at Fragment, tinatawag bago ang kumpletong pagwasak ng component.
  • Ang pagtawag sa onDestroy ay hindi garantisado sa process death — humigit-kumulang 5–8% ng pagtatapos ay nangyayari nang wala ito.
  • Sa onDestroy dapat palayain: network callbacks, sockets, file stream, BroadcastReceiver, ContentObserver.
  • Ang ViewModel.onCleared() ay tinatawag pagkatapos ng onDestroy ng Activity — ang viewModelScope ay awtomatikong kinakansela.
  • Ang onDestroyView sa Fragment (hiwalay sa onDestroy) — ang tamang lugar para i-reset ang mga reference sa View.
  • Ang pagsusuri ng isFinishing() sa onDestroy ay nagbibigay-daan upang makilala ang pagtatapos ng finish() mula sa muling paglikha sa mga pagbabago ng configuration.
  • Huwag umasa sa onDestroy para sa pag-save ng data — gamitin ang onPause o onSaveInstanceState.

Gagawa kami ng mobile application na turnkey

Gumagawa ang IT Sectr ng mga iOS at Android application para sa mga startup at negosyo mula noong 2017. Magpapayo kami sa iyo at magmumungkahi ng pinakamahusay na solusyon.

Pag-usapan ang proyekto

Basahin din