onPause: ano ito, pag-save ng estado ng Activity sa Android

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

onPause — paraan ng lifecycle ng Android na tinatawag kapag nawalan ng focus ng input ang Activity, ngunit nananatiling bahagyang nakikita sa screen. Tinatawag ng system ang onPause bago lumabas ang bagong Activity sa foreground, kapag nagbubukas ng dialog box, kapag pinindot ang button na “Mga Kamakailang App”, o kapag may papasok na tawag. Ang paraang ito — ang huling garantisadong punto para sa pag-save ng data ng user, dahil pagkatapos ng onStop at onDestroy ay maaaring tapusin ng system ang proseso nang walang karagdagang tawag. Sa loob ng onPause, sine-save ng developer ang mga draft, pinapa-pause ang mga animation, pinapalaya ang camera, at isinusulat ang kasalukuyang estado ng UI sa SharedPreferences. Higit pang detalye tungkol sa buong lifecycle ng Activity basahin sa artikulong Activity Lifecycle.

Mga Pangunahing Punto

  • onPause — nawalan ng focus ang Activity ngunit nananatiling nakikita; huling garantisadong punto para sa pag-save ng data
  • Pag-save ng estado — sa onPause sine-save ang kritikal na data ng user: mga draft, text sa mga form, progreso
  • Pagpapalaya ng resources — camera, mikropono, video player ay pinapalaya sa onPause para ibigay sa ibang app
  • Limitasyon sa oras — dapat matapos ang onPause sa loob ng 100 ms; ang paglampas ay nagdudulot ng ANR at naantala ang transition
  • SharedPreferences.apply() — asynchronous na pagsulat sa onPause; ni-block ng commit() ang thread at maaaring magdulot ng ANR
  • onPause vs onStop — onPause sa bahagyang visibility (dialog), onStop sa kumpletong pagtatago (iba pang Activity)
  • onSaveInstanceState — tinatawag pagkatapos ng onPause para i-save ang pansamantalang estado sa Bundle

Ano ang onPause sa Android

onPause — ika-apat na paraan ng lifecycle ng Activity na tinatawag kapag nawalan ng focus ng input ang screen, ngunit nananatiling bahagyang nakikita para sa user. Ito ay isang “transitional” na estado sa pagitan ng aktibong paggana ng app at pagtatago nito. Tinatawag ng system ang onPause sa mga sumusunod na scenario: pagbubukas ng ibang Activity (tinatakpan ng bagong screen ang kasalukuyan), paglitaw ng dialog box (Dialog, PopupWindow, Snackbar ay hindi tumatawag ng onPause, ngunit ang DialogFragment ay tumatawag), pagpindot sa button na “Mga Kamakailang App”, papasok na tawag, pagpindot sa button na “Power” para i-lock ang screen.

Ang pangunahing gawain ng onPause — ihanda ang app para sa posibilidad na maitago o masira. Ito ang huling punto sa lifecycle kung saan makakasigurado ang developer na ma-eexecute ang kanyang code bago magpatuloy ang system sa ibang component. Pagkatapos ng onPause, tinatawag ng system ang onStop (kung ganap na nakatago ang Activity), pagkatapos nito ay maaaring mangyari ang pagkasira ng proseso anumang oras nang walang karagdagang abiso.

Ayon sa dokumentasyon ng Android Developers (2025), ang onPause ay dapat na napakagaan at mabilis. Hanggaang hindi nagbabalik ng kontrol ang onPause, hindi masisimulan ng system ang susunod na Activity — ibig sabihin, nakikita ng user ang pagkaantala sa transition sa pagitan ng mga screen. Inirerekomenda ng Google na tapusin ang onPause sa wala pang 100 millisecond, at lahat ng mahabang operasyon (pag-save sa database, pagsulat sa disk) ay isagawa nang asynchronous sa pamamagitan ng coroutine o apply().

onPause sa Activity

Sa Activity, ang paraang onPause ay tinatawag tuwing hihinto ang screen sa pagiging aktibo, ngunit maaaring patuloy na maipakita nang bahagya. Karaniwang halimbawa: binuksan ng user ang app na “Mapa”, pinindot ang “I-share ang Lokasyon”, at sa itaas ng Mapa ay bumukas ang system dialog para sa pagpili ng app. Ang Activity ng Mapa ay nakakatanggap ng onPause, ngunit nananatiling nakikita sa ilalim ng dialog. Kapag naisara ang dialog, ang Mapa ay nakakatanggap ng onResume nang hindi tinatawag ang onStart (ang screen ay hindi ganap na naitago).

kotlin
class NoteEditorActivity : AppCompatActivity() {
    private var binding: ActivityNoteEditorBinding? = null
    private val prefs by lazy {
        getSharedPreferences("note_drafts", Context.MODE_PRIVATE)
    }

    override fun onPause() {
        super.onPause()

        // Sine-save ang draft ng tala — asynchronous
        prefs.edit()
            .putString("draft_title", binding?.titleInput?.text.toString())
            .putString("draft_body", binding?.bodyInput?.text.toString())
            .putLong("draft_timestamp", System.currentTimeMillis())
            .apply()

        // Pinapa-pause ang video
        binding?.videoPlayer?.pause()

        // Pinapalaya ang eksklusibong resources
        releaseCamera()
        releaseAudioFocus()
    }

    override fun onResume() {
        super.onResume()
        // Ibinabalik ang draft
        binding?.titleInput?.setText(prefs.getString("draft_title", ""))
        binding?.bodyInput?.setText(prefs.getString("draft_body", ""))
        acquireCamera()
        acquireAudioFocus()
    }
}

Ipinapakita ng halimbawang NoteEditorActivity ang tamang paggamit ng onPause: pag-save ng draft sa SharedPreferences sa pamamagitan ng apply(), pag-pause ng video file, pagpapalaya ng camera at audio focus. Bawat tawag — magaan at mabilis, hindi ni-block ang UI thread nang sapat para sa ANR. Pansinin ang pagkakasunod-sunod: ang super.onPause() ay tinatawag sa unang linya — ginagarantiyahan nito na ma-eexecute ang system logic kahit may exception sa user code.

Pag-save ng estado sa onPause

onPause — huling punto kung saan makakapag-save ang developer ng data ng user nang garantisado bago itago o patayin ng system ang app. Pagkatapos ng onStop, maaaring sirain ng system ang proseso kapag kulang ang memory nang hindi tinatawag ang onDestroy. Ang paraang onSaveInstanceState() ay tinatawag pagkatapos ng onPause, ngunit ang Bundle nito ay hindi para sa pangmatagalang storage — nabubuhay lamang ito hanggang sa susunod na onCreate.

SharedPreferences na may apply()

SharedPreferences na may asynchronous na apply() — ang pinakamainam na paraan ng pag-save ng maliit na volume ng data sa onPause. Hindi tulad ng commit(), na synchronously na nagsusulat ng data sa disk at nagbabalik ng boolean, ang apply() ay agad na nagse-save ng data sa memory at nag-iiskedyul ng asynchronous na pagsulat sa disk. Ito ay tumatagal ng wala pang 1 millisecond sa UI thread kumpara sa 10–100 millisecond para sa commit().

kotlin
override fun onPause() {
    super.onPause()

    // ❌ Masama: synchronous na pagsulat ay ni-block ang thread
    // prefs.edit().putInt("score", score).commit()

    // ✅ Mabuti: asynchronous na pagsulat
    prefs.edit().putInt("score", score).apply()

    // Para sa kumplikadong objects — caching sa ViewModel
    viewModel.saveState()
}

Room at coroutine

Para sa structured na data (SQLite sa pamamagitan ng Room) sa onPause ay ginagamit ang coroutine na may lifecycleScope. Awtomatikong kinakansela ng ViewModelScope ang coroutine kapag nasira ang ViewModel, na pumipigil sa pagsulat sa saradong database. Ang pagsulat sa pamamagitan ng Room na may coroutine ay tumatagal ng 5–15 millisecond at hindi ni-block ang UI thread.

kotlin
// Sa ViewModel:
fun saveDraft(title: String, body: String) {
    viewModelScope.launch(Dispatchers.IO) {
        noteDao.insert(NoteDraft(title = title, body = body))
    }
}

// Sa Activity.onPause:
viewModel.saveDraft(
    binding?.titleInput?.text.toString(),
    binding?.bodyInput?.text.toString()
)

onPause sa Fragment

onPause sa Fragment ay tinatawag kapag hihinto ang Fragment sa pagiging aktibo, ngunit maaaring manatiling nakikita. Ito ay nangyayari kapag: ang Fragment ay pinalitan ng ibang Fragment sa pamamagitan ng FragmentTransaction; ang Fragment ay hihinto sa pagiging kasalukuyang pahina sa ViewPager; ang Activity na naglalaman ng Fragment ay nakatanggap ng onPause. Ang interaksyon sa pagitan ng onPause ng Activity at onPause ng Fragment ay mahigpit na hierarchical: una, ang Activity ay nakatatanggap ng onPause, pagkatapos ang lahat ng Fragment nito.

kotlin
class MapFragment : Fragment() {
    private var mapController: MapController? = null

    override fun onPause() {
        super.onPause()
        mapController?.stopFollowMode()
        binding?.mapContainer?.alpha = 0.7f
    }

    override fun onResume() {
        super.onResume()
        binding?.mapContainer?.alpha = 1.0f
        if (isVisible) {
            mapController?.startFollowMode()
        }
    }
}

Pagiging tiyak ng pagtatrabaho sa mga mapa sa onPause: Ang Google Maps at Yandex Maps ay kumokonsumo ng malaking GPU resources sa aktibong follow mode. Kapag nawalan ng focus, makatuwirang i-disable ang animation ng mapa at bawasan ang dalas ng pag-update ng marker, at kapag bumalik ang focus — ibalik ang buong functionality. Ito ay nagpapabuti ng performance at nagbabawas ng konsumo ng kuryente kapag lumilipat sa pagitan ng mga screen.

onPause vs onStop: pagkakaiba at mga scenario

Isa sa mga pinakakaraniwang kalituhan sa mga baguhan na Android developer — hindi pag-unawa sa pagkakaiba ng onPause at onStop. Suriin natin ang bawat scenario at tukuyin ang tamang paraan.

ScenarioonPauseonStop
Pagbubukas ng dialog boxTinatawagHindi tinatawag
Pagbubukas ng bagong Activity (hindi transparent)TinatawagTinatawag
Pagpindot sa button na “Home”TinatawagTinatawag
Pag-lock ng screenTinatawagTinatawag
Papasok na tawagTinatawagTinatawag
Transparent na Activity sa itaas ng kasalukuyanTinatawagHindi tinatawag
Split Screen (kalahating screen)TinatawagHindi tinatawag
PiP (Picture-in-Picture)TinatawagHindi tinatawag

Pangunahing panuntunan: onPause ay tinatawag sa bawat pagkawala ng focus, onStop — lamang sa kumpletong pagkawala ng visibility. Kung mananatiling nakikita ang Activity (kahit bahagya), hindi tinatawag ang onStop. Ito ay kritikal para sa mga mode na Split Screen, PiP, at transparent na Activity — dito gumagana ang onPause/onResume, ngunit ang onStart/onStop ay hindi.

Timing at performance ng onPause

onPause — ang pinaka-kritikal na paraan sa oras sa lifecycle, dahil ni-block nito ang pag-render ng susunod na Activity. Naghihintay ang system na matapos ang onPause ng kasalukuyang Activity bago ipakita ang bago. Kung ang onPause ay tumagal ng higit sa 100 millisecond, mapapansin ng user ang pagkaantala sa transition; kung higit sa 5 segundo — magpapakita ang system ng ANR.

Mga rekomendasyon sa performance

Ang Google Android Performance Guide (2025) ay nagbibigay ng mga sumusunod na rekomendasyon para sa onPause: huwag gumawa ng network requests — dapat kanselahin o ilipat sa WorkManager; huwag magsulat ng malalaking file sa disk — gumamit ng BufferedWriter sa background thread; huwag magsagawa ng kumplikadong SQL queries — ang Room operations ay dapat asynchronous sa pamamagitan ng coroutine; iwasan ang paggawa ng bagong objects — ang garbage collection sa onPause ay nagpapalala ng pagkaantala; gumamit ng apply() sa halip na commit() para sa SharedPreferences.

kotlin
override fun onPause() {
    super.onPause()

    // ❌ Masama: HTTP request ay ni-block ang UI
    // val response = api.syncSave(data).execute()

    // ❌ Masama: synchronous na pagsulat sa file
    // FileOutputStream(file).write(data)

    // ✅ Mabuti: asynchronous na pag-save
    lifecycleScope.launch {
        withContext(Dispatchers.IO) {
            api.saveData(data)
            fileDao.write(data)
        }
    }

    // ✅ Mabuti: magaan na pagsulat sa SharedPreferences
    prefs.edit().putString("key", value).apply()
}

Ang pag-profile ng onPause sa pamamagitan ng Android Studio Profiler (CPU graph) ay nagpapakita ng eksaktong oras ng execution. Kung ang onPause ay tumagal ng higit sa 100 ms, iha-highlight ng Profiler ang paraan ng dilaw, at higit sa 500 ms — ng pula. Sa mga komersyal na proyekto ng IT Sectr, gumagamit kami ng Macrobenchmark tests na awtomatikong sumusuri sa oras ng transition sa pagitan ng Activity at nagse-signal ng performance regression sa CI pipeline.

Mga karaniwang pagkakamali sa onPause

Kahit ang mga experyensadong developer ay nagkakamali sa onPause. Suriin natin ang limang tipikal na problema at ang kanilang mga solusyon.

Synchronous na pagsulat sa database

Ang pagtawag ng Room DAO na may synchronous query (.executeAsObservable() nang walang coroutine) sa onPause ay ni-block ang UI thread ng 10–50 ms. Kung sa oras na iyon ay naganap ang GC o kompetisyon para sa pagsulat sa database, ang pagkaantala ay maaaring umabot ng 200–500 ms. Solusyon: gumamit ng coroutine na may Dispatchers.IO o apply() para sa SharedPreferences.

Pagrehistro ng bagong listeners

Ang onPause ay hindi lugar para magrehistro ng listeners. Kung magrerehistro ka ng BroadcastReceiver sa onPause, mananatili itong aktibo kapag hindi na nakikita ang Activity. Ang pagrehistro ay dapat lamang sa onStart/onResume, at sa onPause/onStop — tanging pag-unregister. Exception — Intent-driven API na nangangailangan ng pagrehistro bago ang tawag.

Pagbalewala ng mga exception

Kung sa onPause ay may hindi nahawakang exception, hindi tinatawag ng system ang onStop at onDestroy. Ang Activity ay nananatiling frozen sa hindi tiyak na estado, at ang onResume sa pagbalik ay maaaring hindi maibalik nang tama ang mga pinalayang resources. Solusyon: balutin ang kritikal na operasyon sa try/catch na may pagla-log sa pamamagitan ng Log.e().

Pag-save ng sobrang data

Hindi kailangang i-save sa onPause ang data na madaling maibalik. Halimbawa, ang mga resulta ng API requests ay naka-cache sa Room o DataStore sa oras ng pagtanggap, hindi sa onPause. I-save lamang ang manu-manong in-input ng user at hindi awtomatikong maibabalik — text sa fields, mga napiling elemento, posisyon ng scroll.

Nakalimutang super.onPause()

Ang super.onPause() ay dapat tawagin, ngunit hindi tulad ng onCreate, ang kawalan nito ay hindi agad nagdudulot ng crash. “Pinapatawad” ng system ang paglaktaw ng super sa onPause, ngunit ang internal state machine ay napupunta sa maling estado. Ang susunod na tawag ng onResume ay maaaring hindi maibalik ang focus ng input, at ang Activity ay mananatiling “nakabitin”. Palaging tawagin ang super.onPause() nang maaga hangga't maaari.

Mga Madalas Itanong

Ano ang mangyayari kung tatawagin ang finish() sa onPause?

Ang pagtawag ng finish() sa onPause ay tatapusin ang Activity kaagad pagkatapos bumalik mula sa paraan. Ito ay tamang scenario kung sa pagkawala ng focus ay kailangan isara ang screen (halimbawa, screen ng authorization kapag na-minimize ang app). Gayunpaman, ang finish() ay magsisimula ng buong cycle ng pagtatapos: onStop → onDestroy, na nagdaragdag ng pagkaantala sa transition. Gamitin ang finish() sa onPause lamang kapag talagang kinakailangan.

Paano naiiba ang onPause sa onSaveInstanceState?

onPause — para sa pag-save ng data na dapat mabuhay sa pagtatapos ng proseso (mga draft sa SharedPreferences/Room). onSaveInstanceState — para sa pag-save ng pansamantalang estado ng UI na kailangan lamang hanggang sa susunod na onCreate (posisyon ng scroll, napiling tab). Ang Bundle ng onSaveInstanceState ay hindi nase-save sa kumpletong pagtatapos ng app — umiiral lamang ito sa memory. Ang data ng onPause ay nase-save sa disk at nabubuhay sa pag-restart.

Maaari bang magbukas ng dialog box sa onPause?

Hindi inirerekomenda. Ang pagbubukas ng dialog o pop-up window sa onPause ay nagdudulot ng WindowLeakException kung ang Activity ay natapos na. Kung kailangan magpakita ng notification sa pagkawala ng focus, gamitin ang NotificationManager (system notifications) — ito ay ligtas at inaasahan ng user. Para sa mga ipinagpaliban na aksyon, gamitin ang AlarmManager o WorkManager.

Bakit ang onPause ay garantisadong lugar ng pag-save, at ang onStop ay hindi?

Garantisadong tinatawag ang onPause bago huminto ang Activity sa pagiging aktibo. Maaaring hindi tawagin ang onStop kung papatayin ng system ang proseso para magbakante ng memory — sa kasong ito, hindi rin tinatawag ang onDestroy. Ang onPause ay ang tanging paraan pagkatapos ng onResume na laging tinatawag, anuman ang dahilan ng pagkawala ng focus. Kaya naman lahat ng kritikal na data ay nase-save mismo sa onPause.

Paano i-test ang onPause sa unit tests?

Para sa pag-test ng onPause ay ginagamit ang Robolectric o FragmentScenario mula sa AndroidX Test. FragmentScenario.create() → moveToState(State.STARTED) → moveToState(State.RESUMED) → moveToState(State.STARTED) ay sunod-sunod na tumatawag ng onPause. Pagkatapos ay tinitiyak kung ang data ay nase-save sa SharedPreferences o kung ang camera ay pinalaya sa pamamagitan ng mock object. Ang Robolectric 4.12+ ay sumusuporta sa emulation ng onPause/onResume nang walang pisikal na device.

Buod

  • onPause — nawalan ng focus ng input ang Activity ngunit nananatiling bahagyang nakikita; huling garantisadong punto para sa pag-save ng data
  • Pag-save — SharedPreferences.apply() o Room sa pamamagitan ng coroutine; bawal ang commit() at synchronous operations
  • Pagpapalaya ng resources — camera, audio focus, video player ay pinapalaya sa onPause para sa ibang app
  • Limit na 100 ms — ni-block ng onPause ang pag-render ng susunod na Activity; paglampas sa limit ay nagdudulot ng ANR
  • onPause vs onStop — onPause sa pagkawala ng focus (napanatili ang visibility), onStop sa kumpletong pagtatago
  • Fragment.onPause — hierarchical na tawag pagkatapos ng Activity.onPause; pagiging tiyak para sa mga mapa at ViewPager
  • Mga karaniwang pagkakamali — synchronous na pagsulat, pagrehistro ng listeners, pagbalewala ng try/catch, sobrang pag-save
  • super.onPause() — tawagin nang maaga hangga't maaari; ang paglaktaw ay hindi nagdudulot ng crash ngunit nasisira ang state machine

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