onPause, bir Activity giriş odağını kaybettiğinde ancak ekranda kısmen görünür kaldığında çağrılan bir Android yaşam döngüsü yöntemidir. Sistem, yeni bir Activity ön plana çıkmadan önce, bir iletişim kutusu açıldığında, Son Uygulamalar düğmesine basıldığında veya gelen bir arama olduğunda onPause'u çağırır. Bu yöntem, kullanıcı verilerini kaydetmek için son garantili noktadır, çünkü onStop ve onDestroy'den sonra sistem ek çağrı olmadan işlemi sonlandırabilir. onPause içinde geliştirici taslakları kaydeder, animasyonları duraklatır, kamerayı serbest bırakır ve geçerli UI durumunu SharedPreferences'a yazar. Tam Activity yaşam döngüsü hakkında daha fazla ayrıntı için Activity Lifecycle makalesini okuyun.
Önemli Noktalar
onPause, Activity yaşam döngüsünün dördüncü yöntemidir ve ekran giriş odağını kaybettiğinde ancak kullanıcıya kısmen görünür kaldığında çağrılır. Uygulamanın aktif olarak çalışması ile gizlenmesi arasında bir «geçiş» durumudur. Sistem onPause'u şu senaryolarda çağırır: başka bir Activity açılması (yeni bir ekran mevcut ekranı kısmen kaplar), bir iletişim kutusu penceresinin görünmesi (Dialog, PopupWindow, Snackbar onPause'u tetiklemez, ancak DialogFragment tetikler), Son Uygulamalar düğmesine basılması, gelen arama, ekranı kilitlemek için güç düğmesine basılması.
onPause'un ana görevi, uygulamayı gizlenme veya yok edilme olasılığına hazırlamaktır. Bu, geliştiricinin sistem başka bir bileşene geçiş yapmadan önce kodunun çalıştırılacağından emin olabileceği yaşam döngüsündeki son noktadır. onPause'dan sonra sistem onStop'u çağırır (Activity tamamen gizlenmişse), ardından işlem ek bildirim olmadan herhangi bir zamanda sonlandırılabilir.
Android Developers belgelerine (2025) göre, onPause mümkün olduğunca hafif ve hızlı olmalıdır. onPause kontrolü geri verene kadar sistem sonraki Activity'i başlatamaz — bu, kullanıcının ekran geçişinde gecikme gördüğü anlamına gelir. Google, onPause'un 100 milisaniyeden az sürede tamamlanmasını önerir ve tüm uzun işlemler (veritabanına kaydetme, diske yazma) eşzamansız olarak coroutines veya apply() aracılığıyla yapılmalıdır.
Bir Activity'de, onPause yöntemi ekran artık aktif olmadığında ancak kısmen görüntülenmeye devam edebildiğinde her seferinde çağrılır. Tipik bir örnek: kullanıcı Haritalar uygulamasını açar, Konumu Paylaş'a dokunur ve Haritalar'ın üzerinde bir sistem uygulama seçimi iletişim kutusu belirir. Haritalar Activity'si onPause alır ancak iletişim kutusunun altında görünür kalır. İletişim kutusu kapatıldığında, Haritalar onStart çağrılmadan onResume alır (ekran tamamen gizlenmemiştir).
class NoteEditorActivity : AppCompatActivity() {
private var binding: ActivityNoteEditorBinding? = null
private val prefs by lazy {
getSharedPreferences("note_drafts", Context.MODE_PRIVATE)
}
override fun onPause() {
super.onPause()
// Not taslağını kaydet — async
prefs.edit()
.putString("draft_title", binding?.titleInput?.text.toString())
.putString("draft_body", binding?.bodyInput?.text.toString())
.putLong("draft_timestamp", System.currentTimeMillis())
.apply()
// Videoyu duraklat
binding?.videoPlayer?.pause()
// Özel kaynakları serbest bırak
releaseCamera()
releaseAudioFocus()
}
override fun onResume() {
super.onResume()
// Taslağı geri yükle
binding?.titleInput?.setText(prefs.getString("draft_title", ""))
binding?.bodyInput?.setText(prefs.getString("draft_body", ""))
acquireCamera()
acquireAudioFocus()
}
}
NoteEditorActivity örneği, onPause'un doğru şekilde işlenmesini gösterir: apply() aracılığıyla SharedPreferences'a taslak kaydetme, video dosyasını duraklatma, kamerayı ve ses odağını serbest bırakma. Her çağrı hafif ve hızlıdır, ANR'yi tetikleyecek kadar UI iş parçacığını bloke etmez. Sıraya dikkat edin: super.onPause() ilk satırda çağrılır — bu, kullanıcı kodunda bir istisna olsa bile sistem mantığının çalışmasını garanti eder.
onPause, uygulama gizlenmeden veya sistem tarafından sonlandırılmadan önce geliştiricinin kullanıcı verilerini güvenilir bir şekilde kaydedebileceği son noktadır. onStop'dan sonra sistem, bellek yetersizse onDestroy'u çağırmadan işlemi sonlandırabilir. onSaveInstanceState() yöntemi onPause'dan sonra çağrılır, ancak Bundle'ı uzun süreli depolama için tasarlanmamıştır — yalnızca sonraki onCreate'e kadar yaşar.
Async apply() ile SharedPreferences, onPause'da küçük miktarlarda veri kaydetmenin optimal yoludur commit()'in aksine, verileri senkron olarak diske yazan ve boolean döndüren, apply() verileri hemen belleğe kaydeder ve async disk yazmasını planlar. Bu, commit()'in 10–100 milisaniyesine karşı UI iş parçacığında 1 milisaniyeden az sürer.
override fun onPause() {
super.onPause()
// ❌ Kötü: senkron yazma iş parçacığını bloke eder
// prefs.edit().putInt("score", score).commit()
// ✅ İyi: async yazma
prefs.edit().putInt("score", score).apply()
// Karmaşık nesneler için — ViewModel'de önbelleğe alma
viewModel.saveState()
}
onPause'da yapılandırılmış veriler (Room aracılığıyla SQLite) için lifecycleScope ile coroutines kullanılır. ViewModelScope, ViewModel yok edildiğinde coroutine'i otomatik olarak iptal eder ve kapalı bir veritabanına yazmayı önler. Coroutines ile Room aracılığıyla yazma 5–15 milisaniye sürer ve UI iş parçacığını bloke etmez.
// ViewModel'de:
fun saveDraft(title: String, body: String) {
viewModelScope.launch(Dispatchers.IO) {
noteDao.insert(NoteDraft(title = title, body = body))
}
}
// Activity.onPause'da:
viewModel.saveDraft(
binding?.titleInput?.text.toString(),
binding?.bodyInput?.text.toString()
)
Fragment'te onPause, Fragment artık aktif olmadığında ancak görünür kalabildiğinde çağrılır. Bu şu durumlarda olur: bir Fragment, FragmentTransaction aracılığıyla başka bir Fragment ile değiştirildiğinde; bir Fragment, ViewPager'da geçerli sayfa olmaktan çıktığında; Fragment'i içeren Activity onPause aldığında. Activity onPause ile Fragment onPause arasındaki etkileşim kesinlikle hiyerarşiktir: önce Activity onPause alır, ardından tüm Fragment'leri alır.
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()
}
}
}
onPause'da haritalarla çalışmanın özellikleri: Google Maps ve Yandex Maps, aktif takip modunda önemli GPU kaynakları tüketir. Odak kaybedildiğinde, harita animasyonunu devre dışı bırakmak ve işaretçi güncelleme sıklığını azaltmak mantıklıdır ve odak geri geldiğinde tam işlevselliği geri yüklemek gerekir. Bu, ekranlar arasında geçiş yaparken performansı artırır ve güç tüketimini azaltır.
Yeni başlayan Android geliştiricileri arasındaki en yaygın kafa karışıklıklarından biri, onPause ve onStop arasındaki farkı anlamamaktır. Her senaryoyu inceleyelim ve doğru yöntemi belirleyelim.
| Senaryo | onPause | onStop |
|---|---|---|
| İletişim kutusu penceresi açma | Çağrılır | Çağrılmaz |
| Yeni Activity açma (saydam olmayan) | Çağrılır | Çağrılır |
| Ana Ekran düğmesine basma | Çağrılır | Çağrılır |
| Ekran kilidi | Çağrılır | Çağrılır |
| Gelen arama | Çağrılır | Çağrılır |
| Üstte saydam Activity | Çağrılır | Çağrılmaz |
| Bölünmüş Ekran (yarım ekran) | Çağrılır | Çağrılmaz |
| PiP (Resim İçinde Resim) | Çağrılır | Çağrılmaz |
Ana kural: onPause herhangi bir odak kaybında çağrılır, onStop yalnızca görünürlük tamamen kaybolduğunda çağrılır. Activity görünür kalırsa (kısmen bile olsa), onStop çağrılmaz. Bu, Bölünmüş Ekran, PiP ve saydam Activity modları için kritik öneme sahiptir — burada onPause/onResume çalışır, ancak onStart/onStop çalışmaz.
onPause, sonraki Activity'nin işlenmesini bloke ettiği için zaman açısından en kritik yaşam döngüsü yöntemidir. Sistem, yenisini göstermeden önce mevcut Activity'nin onPause'unun tamamlanmasını bekler. onPause 100 milisaniyeden uzun sürerse, kullanıcı geçişte gecikme fark eder; 5 saniyeden uzun sürerse sistem ANR gösterir.
Google Android Performans Kılavuzu (2025), onPause için aşağıdaki önerileri sunar: ağ istekleri yapmayın — iptal edilmeli veya WorkManager'a taşınmalıdır; diske büyük dosyalar yazmayın — arka plan iş parçacığında BufferedWriter kullanın; karmaşık SQL sorguları çalıştırmayın — Room işlemleri coroutines aracılığıyla async olmalıdır; yeni nesneler oluşturmaktan kaçının — onPause'da çöp toplama gecikmeyi kötüleştirir; SharedPreferences için commit() yerine apply() kullanın.
override fun onPause() {
super.onPause()
// ❌ Kötü: HTTP isteği UI'yı bloke eder
// val response = api.syncSave(data).execute()
// ❌ Kötü: dosyaya senkron yazma
// FileOutputStream(file).write(data)
// ✅ İyi: async kaydetme
lifecycleScope.launch {
withContext(Dispatchers.IO) {
api.saveData(data)
fileDao.write(data)
}
}
// ✅ İyi: SharedPreferences'a hafif yazma
prefs.edit().putString("key", value).apply()
}
Android Studio Profiler (CPU izi) aracılığıyla onPause profil oluşturma, tam yürütme süresini gösterir. onPause 100 ms'den uzun sürerse, Profiler yöntemi sarı renkle vurgular ve 500 ms'den uzunsa kırmızıyla. IT Sectr'daki ticari projelerde, Activity'ler arasındaki geçiş süresini otomatik olarak kontrol eden ve CI hattındaki performans düşüşlerini bildiren Macrobenchmark testleri kullanıyoruz.
Deneyimli geliştiriciler bile onPause'da hatalar yapar. Beş tipik sorunu ve çözümlerini inceleyelim.
onPause'da senkron sorgu (.executeAsObservable() coroutines olmadan) ile Room DAO çağırmak UI iş parçacığını 10–50 ms boyunca bloke eder. Aynı anda GC veya yazma çekişmesi olursa, gecikme 200–500 ms'ye ulaşabilir. Çözüm: Dispatchers.IO ile coroutines veya SharedPreferences için apply() kullanın.
onPause, dinleyici kaydetmek için yer değildir. onPause'da bir BroadcastReceiver kaydederseniz, Activity artık görünür olmadığında bile etkin kalır. Kayıt yalnızca onStart/onResume'da yapılmalı ve onPause/onStop'da yalnızca kaydı iptal etme yapılmalıdır. İstisna, çağrıdan önce kayıt gerektiren Intent tabanlı API'lerdir.
onPause'da işlenmeyen bir istisna oluşursa, sistem onStop ve onDestroy'u çağırmaz. Activity tanımsız bir durumda takılıp kalır ve geri dönüşte onResume, serbest bırakılan kaynakları doğru şekilde geri yüklemeyebilir. Çözüm: kritik işlemleri Log.e() ile günlüğe kaydetmeyle birlikte try/catch içine alın.
Kolayca geri yüklenebilen verileri onPause'da kaydetmeye gerek yoktur. Örneğin, API istek sonuçları onPause'da değil, alınma anında Room veya DataStore'da önbelleğe alınır. Yalnızca kullanıcının manuel olarak girdiği ve otomatik olarak geri yüklenemeyenleri kaydedin — alanlardaki metin, seçilen öğeler, kaydırma konumu.
super.onPause() çağrılmalıdır, ancak onCreate'in aksine, atlanması hemen çökmeye neden olmaz. Sistem, onPause'da super'in eksikliğini «affeder», ancak iç durum makinesi yanlış bir duruma girer. Sonraki onResume çağrısı giriş odağını geri yüklemeyebilir ve Activity «donmuş» kalır. Her zaman super.onPause()'u mümkün olduğunca erken çağırın.
Sıkça Sorulan Sorular
onPause'da finish() çağırmak, yöntemden döndükten hemen sonra Activity'yi sonlandırır. Bu, odak kaybedildiğinde ekranın kapatılması gerekiyorsa (örneğin, uygulama simge durumuna küçültüldüğünde yetkilendirme ekranı) geçerli bir senaryodur. Ancak, finish() tam sonlandırma döngüsünü tetikler: onStop onDestroy, bu da geçişe gecikme ekler. onPause'da finish()'i yalnızca gerçekten gerekli olduğunda kullanın.
onPause, işlem sonlandırmasından sonra hayatta kalması gereken verileri kaydetmek içindir (SharedPreferences/Room'daki taslaklar). onSaveInstanceState, yalnızca sonraki onCreate'e kadar gereken geçici UI durumunu kaydetmek içindir (kaydırma konumu, seçili sekme). onSaveInstanceState Bundle'ı uygulama tamamen sonlandırıldığında korunmaz — yalnızca bellekte bulunur. onPause verileri diske kaydedilir ve yeniden başlatmadan sonra hayatta kalır.
Önerilmez. onPause'da bir iletişim kutusu veya açılır pencere açmak, Activity zaten sonlandırılmışsa WindowLeakException'a neden olur. Odak kaybedildiğinde bir bildirim göstermeniz gerekiyorsa, NotificationManager'ı (sistem bildirimleri) kullanın — bu güvenlidir ve kullanıcı tarafından beklenir. Ertelenmiş eylemler için AlarmManager veya WorkManager kullanın.
onPause'un Activity aktif olmayı bırakmadan önce çağrılması garantilidir Sistem belleği boşaltmak için işlemi öldürürse onStop çağrılmayabilir — bu durumda onDestroy da çağrılmaz. onPause, onResume'dan sonra odak kaybının nedeni ne olursa olsun her zaman çağrılan tek yöntemdir. Bu nedenle, tüm kritik veriler tam olarak onPause'da kaydedilir.
onPause'u test etmek için Robolectric veya AndroidX Test'ten FragmentScenario kullanılır. FragmentScenario.create() moveToState(State.STARTED) moveToState(State.RESUMED) moveToState(State.STARTED) sırayla onPause'u çağırır. Ardından, verilerin SharedPreferences'a kaydedildiği veya kameranın bir mock nesnesi aracılığıyla serbest bırakıldığı doğrulanır. Robolectric 4.12+, fiziksel bir cihaz olmadan onPause/onResume öykünmesini destekler.
Özet
Anahtar teslim bir mobil uygulama geliştireceğiz
IT Sectr, 2017'den beri girişimler ve işletmeler için iOS ve Android uygulamaları oluşturmaktadır. Size danışmanlık yapacak ve en iyi çözümü önereceğiz.
Ayrıca okuyun