onPause: apa itu, menyimpan status Activity di Android

Penulis: IT Sectr Diterbitkan: 2026-03-04 Waktu membaca: 10 mnt

onPause — metode siklus hidup Android yang dipanggil ketika Activity kehilangan fokus input, tetapi tetap terlihat sebagian di layar. Sistem memanggil onPause sebelum Activity baru muncul ke latar depan, saat membuka kotak dialog, saat menekan tombol “Aplikasi Terbaru”, atau saat panggilan masuk. Metode ini — titik terakhir yang dijamin untuk menyimpan data pengguna, karena setelah onStop dan onDestroy sistem dapat mengakhiri proses tanpa panggilan tambahan. Di dalam onPause, pengembang menyimpan draf, menjeda animasi, melepaskan kamera, dan menulis status UI saat ini ke SharedPreferences. Detail tentang siklus hidup Activity lengkap baca di artikel Activity Lifecycle.

Poin Utama

  • onPause — Activity kehilangan fokus tetapi tetap terlihat; titik terakhir yang dijamin untuk menyimpan data
  • Penyimpanan status — di onPause data kritis pengguna disimpan: draf, teks di formulir, kemajuan
  • Pelepasan sumber daya — kamera, mikrofon, pemutar video dilepaskan di onPause untuk diberikan ke aplikasi lain
  • Batas waktu — onPause harus selesai dalam 100 md; pelampauan menyebabkan ANR dan menunda transisi
  • SharedPreferences.apply() — penulisan asinkron di onPause; commit() memblokir utas dan dapat menyebabkan ANR
  • onPause vs onStop — onPause saat visibilitas sebagian (dialog), onStop saat penyembunyian penuh (Activity lain)
  • onSaveInstanceState — dipanggil setelah onPause untuk menyimpan status sementara di Bundle

Apa itu onPause di Android

onPause — metode keempat siklus hidup Activity yang dipanggil ketika layar kehilangan fokus input, tetapi tetap terlihat sebagian bagi pengguna. Ini adalah keadaan “transisi” antara kerja aktif aplikasi dan penyembunyiannya. Sistem memanggil onPause dalam skenario berikut: membuka Activity lain (layar baru menutupi yang saat ini), munculnya kotak dialog (Dialog, PopupWindow, Snackbar tidak memanggil onPause, tetapi DialogFragment memanggil), menekan tombol “Aplikasi Terbaru”, panggilan masuk, menekan tombol “Daya” untuk mengunci layar.

Tugas utama onPause — mempersiapkan aplikasi untuk kemungkinan disembunyikan atau dihancurkan. Ini adalah titik terakhir dalam siklus hidup di mana pengembang dapat yakin bahwa kodenya akan dijalankan sebelum sistem melanjutkan transisi ke komponen lain. Setelah onPause, sistem memanggil onStop (jika Activity disembunyikan sepenuhnya), setelah itu penghancuran proses dapat terjadi kapan saja tanpa pemberitahuan tambahan.

Menurut dokumentasi Android Developers (2025), onPause harus seringan dan secepat mungkin. Selama onPause belum mengembalikan kendali, sistem tidak dapat memulai Activity berikutnya — ini berarti pengguna melihat keterlambatan transisi antar layar. Google merekomendasikan untuk menyelesaikan onPause dalam kurang dari 100 milidetik, dan semua operasi panjang (penyimpanan ke database, penulisan ke disk) dilakukan secara asinkron melalui coroutine atau apply().

onPause di Activity

Di Activity, metode onPause dipanggil setiap kali layar berhenti aktif, tetapi mungkin masih dapat ditampilkan sebagian. Contoh tipikal: pengguna membuka aplikasi “Peta”, menekan “Bagikan Lokasi”, dan di atas Peta terbuka dialog sistem pemilihan aplikasi. Activity Peta mendapatkan onPause, tetapi tetap terlihat di bawah dialog. Saat dialog ditutup, Peta mendapatkan onResume tanpa panggilan onStart (layar tidak disembunyikan sepenuhnya).

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()

        // Menyimpan draf catatan — asinkron
        prefs.edit()
            .putString("draft_title", binding?.titleInput?.text.toString())
            .putString("draft_body", binding?.bodyInput?.text.toString())
            .putLong("draft_timestamp", System.currentTimeMillis())
            .apply()

        // Menjeda video
        binding?.videoPlayer?.pause()

        // Melepaskan sumber daya eksklusif
        releaseCamera()
        releaseAudioFocus()
    }

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

Contoh NoteEditorActivity menunjukkan kerja yang benar dengan onPause: menyimpan draf di SharedPreferences melalui apply(), menjeda file video, melepaskan kamera dan fokus audio. Setiap panggilan — ringan dan cepat, tidak memblokir utas UI cukup untuk ANR. Perhatikan urutan: super.onPause() dipanggil di baris pertama — ini menjamin bahwa logika sistem akan dijalankan bahkan saat terjadi eksepsi di kode pengguna.

Menyimpan status di onPause

onPause — titik terakhir di mana pengembang dapat menyimpan data pengguna secara dijamin sebelum aplikasi disembunyikan atau dihentikan oleh sistem. Setelah onStop, sistem dapat menghancurkan proses saat kekurangan memori tanpa memanggil onDestroy. Metode onSaveInstanceState() dipanggil setelah onPause, tetapi Bundle-nya tidak ditujukan untuk penyimpanan jangka panjang — hanya hidup hingga onCreate berikutnya.

SharedPreferences dengan apply()

SharedPreferences dengan apply() asinkron — cara optimal untuk menyimpan data volume kecil di onPause. Berbeda dengan commit(), yang secara sinkron menulis data ke disk dan mengembalikan boolean, apply() segera menyimpan data di memori dan menjadwalkan penulisan asinkron ke disk. Ini memakan waktu kurang dari 1 milidetik di utas UI dibandingkan 10–100 milidetik untuk commit().

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

    // ❌ Buruk: penulisan sinkron memblokir utas
    // prefs.edit().putInt("score", score).commit()

    // ✅ Baik: penulisan asinkron
    prefs.edit().putInt("score", score).apply()

    // Untuk objek kompleks — caching di ViewModel
    viewModel.saveState()
}

Room dan coroutine

Untuk data terstruktur (SQLite melalui Room) di onPause digunakan coroutine dengan lifecycleScope. ViewModelScope secara otomatis membatalkan coroutine saat ViewModel dihancurkan, mencegah penulisan ke database yang ditutup. Penulisan melalui Room dengan coroutine memakan waktu 5–15 milidetik dan tidak memblokir utas UI.

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

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

onPause di Fragment

onPause di Fragment dipanggil ketika Fragment berhenti aktif, tetapi mungkin tetap terlihat. Ini terjadi ketika: Fragment digantikan oleh Fragment lain melalui FragmentTransaction; Fragment berhenti menjadi halaman saat ini di ViewPager; Activity yang mengandung Fragment mendapatkan onPause. Interaksi antara onPause Activity dan onPause Fragment bersifat hierarkis ketat: pertama Activity mendapatkan onPause, kemudian semua Fragment-nya.

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()
        }
    }
}

Spesifik bekerja dengan peta di onPause: Google Maps dan Yandex Maps mengonsumsi sumber daya GPU yang signifikan dalam mode pelacakan aktif (follow mode). Saat kehilangan fokus, masuk akal untuk menonaktifkan animasi peta dan mengurangi frekuensi pembaruan marker, dan saat fokus kembali — memulihkan fungsionalitas penuh. Ini meningkatkan kinerja dan mengurangi konsumsi daya saat beralih antar layar.

onPause vs onStop: perbedaan dan skenario

Salah satu kebingungan paling umum di kalangan pengembang Android pemula — tidak memahami perbedaan antara onPause dan onStop. Mari kita bahas setiap skenario dan tentukan metode yang benar.

SkenarioonPauseonStop
Membuka kotak dialogDipanggilTidak dipanggil
Membuka Activity baru (tidak transparan)DipanggilDipanggil
Menekan tombol “Beranda”DipanggilDipanggil
Mengunci layarDipanggilDipanggil
Panggilan masukDipanggilDipanggil
Activity transparan di atas yang saat iniDipanggilTidak dipanggil
Split Screen (setengah layar)DipanggilTidak dipanggil
PiP (Picture-in-Picture)DipanggilTidak dipanggil

Aturan utama: onPause dipanggil pada setiap kehilangan fokus, onStop — hanya pada kehilangan visibilitas penuh. Jika Activity tetap terlihat (bahkan sebagian), onStop tidak dipanggil. Ini sangat penting untuk mode Split Screen, PiP, dan Activity transparan — di sini onPause/onResume berfungsi, tetapi onStart/onStop tidak.

Waktu dan kinerja onPause

onPause — metode yang paling kritis waktu dalam siklus hidup, karena memblokir rendering Activity berikutnya. Sistem menunggu penyelesaian onPause Activity saat ini sebelum menampilkan yang baru. Jika onPause berjalan lebih dari 100 milidetik, pengguna melihat keterlambatan transisi; jika lebih dari 5 detik — sistem menampilkan ANR.

Rekomendasi kinerja

Panduan Kinerja Android Google (2025) memberikan rekomendasi berikut untuk onPause: jangan lakukan permintaan jaringan — harus dibatalkan atau dipindahkan ke WorkManager; jangan tulis file besar ke disk — gunakan BufferedWriter di utas latar belakang; jangan lakukan kueri SQL kompleks — operasi Room harus asinkron melalui coroutine; hindari membuat objek baru — garbage collection di onPause memperburuk keterlambatan; gunakan apply() alih-alih commit() untuk SharedPreferences.

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

    // ❌ Buruk: permintaan HTTP memblokir UI
    // val response = api.syncSave(data).execute()

    // ❌ Buruk: penulisan sinkron ke file
    // FileOutputStream(file).write(data)

    // ✅ Baik: penyimpanan asinkron
    lifecycleScope.launch {
        withContext(Dispatchers.IO) {
            api.saveData(data)
            fileDao.write(data)
        }
    }

    // ✅ Baik: penulisan ringan ke SharedPreferences
    prefs.edit().putString("key", value).apply()
}

Profiling onPause melalui Android Studio Profiler (grafik CPU) menunjukkan waktu eksekusi yang tepat. Jika onPause memakan waktu lebih dari 100 ms, Profiler menyorot metode dengan warna kuning, dan lebih dari 500 ms — merah. Di proyek komersial IT Sectr, kami menggunakan tes Macrobenchmark yang secara otomatis memeriksa waktu transisi antar Activity dan memberi sinyal regresi kinerja di pipeline CI.

Kesalahan umum di onPause

Bahkan pengembang berpengalaman pun membuat kesalahan di onPause. Mari kita bahas lima masalah tipikal dan solusinya.

Penulisan sinkron ke database

Pemanggilan Room DAO dengan kueri sinkron (.executeAsObservable() tanpa coroutine) di onPause memblokir utas UI selama 10–50 md. Jika pada saat itu terjadi GC atau persaingan untuk menulis ke database, keterlambatan bisa mencapai 200–500 md. Solusi: gunakan coroutine dengan Dispatchers.IO atau apply() untuk SharedPreferences.

Pendaftaran pendengar baru

onPause bukan tempat untuk mendaftarkan pendengar. Jika Anda mendaftarkan BroadcastReceiver di onPause, ia akan tetap aktif ketika Activity sudah tidak terlihat. Pendaftaran hanya boleh dilakukan di onStart/onResume, dan di onPause/onStop — hanya pembatalan pendaftaran. Pengecualian — API Intent-driven yang memerlukan pendaftaran sebelum pemanggilan.

Mengabaikan eksepsi

Jika di onPause terjadi eksepsi yang tidak tertangani, sistem tidak memanggil onStop dan onDestroy. Activity macet dalam keadaan tidak menentu, dan onResume saat kembali mungkin tidak memulihkan sumber daya yang telah dilepaskan dengan benar. Solusi: bungkus operasi kritis dalam try/catch dengan pencatatan melalui Log.e().

Menyimpan data berlebihan

Tidak perlu menyimpan di onPause data yang mudah dipulihkan. Misalnya, hasil permintaan API di-cache di Room atau DataStore saat diterima, bukan di onPause. Simpan hanya apa yang dimasukkan pengguna secara manual dan tidak dapat dipulihkan secara otomatis — teks di kolom, elemen yang dipilih, posisi scroll.

Lupa super.onPause()

super.onPause() harus dipanggil, tetapi tidak seperti onCreate, ketiadaannya tidak menyebabkan crash langsung. Sistem “maafkan” melewatkan super di onPause, tetapi mesin status internal masuk ke keadaan yang salah. Panggilan onResume berikutnya mungkin tidak memulihkan fokus input, dan Activity tetap “beku”. Selalu panggil super.onPause() sedini mungkin.

Pertanyaan yang Sering Diajukan

Apa yang terjadi jika finish() dipanggil di onPause?

Pemanggilan finish() di onPause akan mengakhiri Activity segera setelah kembali dari metode. Ini adalah skenario yang benar jika saat kehilangan fokus layar harus ditutup (misalnya, layar otorisasi saat aplikasi diminimalkan). Namun, finish() memulai siklus penyelesaian penuh: onStop → onDestroy, yang menambah keterlambatan pada transisi. Gunakan finish() di onPause hanya ketika benar-benar diperlukan.

Apa perbedaan onPause dengan onSaveInstanceState?

onPause — untuk menyimpan data yang harus bertahan dari penghentian proses (draf di SharedPreferences/Room). onSaveInstanceState — untuk menyimpan status UI sementara yang hanya diperlukan hingga onCreate berikutnya (posisi scroll, tab yang dipilih). Bundle onSaveInstanceState tidak disimpan saat aplikasi dihentikan sepenuhnya — hanya ada di memori. Data onPause disimpan di disk dan bertahan dari restart.

Bisakah kotak dialog dibuka di onPause?

Tidak disarankan. Membuka dialog atau jendela pop-up di onPause menyebabkan WindowLeakException jika Activity sudah diakhiri. Jika perlu menampilkan notifikasi saat kehilangan fokus, gunakan NotificationManager (notifikasi sistem) — ini aman dan diharapkan oleh pengguna. Untuk tindakan tertunda, gunakan AlarmManager atau WorkManager.

Mengapa onPause adalah tempat penyimpanan yang dijamin, sedangkan onStop tidak?

onPause dijamin dipanggil sebelum Activity berhenti aktif. onStop mungkin tidak dipanggil jika sistem menghentikan proses untuk membebaskan memori — dalam hal ini onDestroy juga tidak dipanggil. onPause adalah satu-satunya metode setelah onResume yang selalu dipanggil, terlepas dari alasan kehilangan fokus. Oleh karena itu, semua data kritis disimpan tepat di onPause.

Bagaimana cara menguji onPause di unit test?

Untuk menguji onPause digunakan Robolectric atau FragmentScenario dari AndroidX Test. FragmentScenario.create() → moveToState(State.STARTED) → moveToState(State.RESUMED) → moveToState(State.STARTED) secara sekuensial memanggil onPause. Kemudian diperiksa apakah data telah disimpan di SharedPreferences atau apakah kamera telah dilepaskan melalui objek mock. Robolectric 4.12+ mendukung emulasi onPause/onResume tanpa perangkat fisik.

Ringkasan

  • onPause — Activity kehilangan fokus input tetapi tetap terlihat sebagian; titik terakhir yang dijamin untuk menyimpan data
  • Penyimpanan — SharedPreferences.apply() atau Room melalui coroutine; commit() dan operasi sinkron dilarang
  • Pelepasan sumber daya — kamera, fokus audio, pemutar video dilepaskan di onPause untuk aplikasi lain
  • Batas 100 md — onPause memblokir rendering Activity berikutnya; pelampauan batas menyebabkan ANR
  • onPause vs onStop — onPause saat kehilangan fokus (visibilitas dipertahankan), onStop saat penyembunyian penuh
  • Fragment.onPause — panggilan hierarkis setelah Activity.onPause; spesifik untuk peta dan ViewPager
  • Kesalahan umum — penulisan sinkron, pendaftaran pendengar, mengabaikan try/catch, penyimpanan berlebihan
  • super.onPause() — panggil sedini mungkin; melewatkannya tidak menyebabkan crash tetapi merusak mesin status

Kami akan mengembangkan aplikasi seluler turnkey

IT Sectr membuat aplikasi iOS dan Android untuk startup dan bisnis sejak 2017. Kami akan memberi saran dan mengusulkan solusi terbaik.

Diskusikan proyek

Baca juga