onPause — az Android életciklus metódusa, amely akkor hívódik meg, amikor az Activity elveszíti a beviteli fókuszt, de részben látható marad a képernyőn. A rendszer onPause-t hív meg, mielőtt egy új Activity előtérbe kerül, párbeszédablak megnyitásakor, a „Legutóbbi alkalmazások” gomb megnyomásakor vagy bejövő hívás esetén. Ez a metódus az utolsó garantált pont a felhasználói adatok mentésére, mivel onStop és onDestroy után a rendszer további hívások nélkül befejezheti a folyamatot. Az onPause-on belül a fejlesztő elmenti a piszkozatokat, felfüggeszti az animációkat, felszabadítja a kamerát és az aktuális UI állapotot SharedPreferences-be írja. Az Activity teljes életciklusáról bővebben a Activity Lifecycle cikkben olvashat.
Főbb pontok
onPause — az Activity életciklus negyedik metódusa, amely akkor hívódik meg, amikor a képernyő elveszíti a beviteli fókuszt, de részben látható marad a felhasználó számára. Ez egy „átmeneti” állapot az alkalmazás aktív működése és elrejtése között. A rendszer onPause-t hív meg a következő forgatókönyvekben: másik Activity megnyitása (új képernyő eltakarja a jelenlegit), párbeszédablak megjelenése (Dialog, PopupWindow, Snackbar nem hív onPause-t, de a DialogFragment igen), a „Legutóbbi alkalmazások” gomb megnyomása, bejövő hívás, a „Bekapcsolás” gomb megnyomása a képernyő lezárásához.
Az onPause fő feladata — felkészíteni az alkalmazást arra, hogy elrejtésre vagy megsemmisítésre kerülhet. Ez az utolsó pont az életciklusban, ahol a fejlesztő biztos lehet benne, hogy a kódja lefut, mielőtt a rendszer továbblép egy másik komponenshez. Az onPause után a rendszer onStop-ot hív (ha az Activity teljesen elrejtődik), ezután a folyamat megsemmisítése bármikor bekövetkezhet további értesítés nélkül.
Az Android Developers (2025) dokumentáció szerint az onPause-nak a lehető legkönnyebbnek és leggyorsabbnak kell lennie. Amíg onPause nem adja vissza a vezérlést, a rendszer nem indíthatja el a következő Activity-t — ez azt jelenti, hogy a felhasználó késlekedést lát a képernyők közötti átmenetben. A Google azt javasolja, hogy az onPause 100 ezredmásodpercnél rövidebb idő alatt fejeződjön be, és minden hosszú műveletet (mentés adatbázisba, írás lemezre) aszinkron módon, korutinokkal vagy apply()-vel végezzünk.
Activity-ben az onPause metódus minden alkalommal meghívódik, amikor a képernyő megszűnik aktív lenni, de továbbra is részben megjeleníthető. Tipikus példa: a felhasználó megnyitja a „Térképek” alkalmazást, megnyomja a „Hely megosztása” gombot, és a Térképek felett megjelenik egy rendszer párbeszédablak az alkalmazás kiválasztásához. A Térképek Activity-je onPause-t kap, de látható marad a párbeszédablak alatt. Amikor a párbeszédablak bezárul, a Térképek onResume-t kap az onStart meghívása nélkül (a képernyő nem volt teljesen elrejtve).
class NoteEditorActivity : AppCompatActivity() {
private var binding: ActivityNoteEditorBinding? = null
private val prefs by lazy {
getSharedPreferences("note_drafts", Context.MODE_PRIVATE)
}
override fun onPause() {
super.onPause()
// Elmentjük a jegyzet piszkozatát — aszinkron
prefs.edit()
.putString("draft_title", binding?.titleInput?.text.toString())
.putString("draft_body", binding?.bodyInput?.text.toString())
.putLong("draft_timestamp", System.currentTimeMillis())
.apply()
// Felfüggesztjük a videót
binding?.videoPlayer?.pause()
// Felszabadítjuk az exkluzív erőforrásokat
releaseCamera()
releaseAudioFocus()
}
override fun onResume() {
super.onResume()
// Visszaállítjuk a piszkozatot
binding?.titleInput?.setText(prefs.getString("draft_title", ""))
binding?.bodyInput?.setText(prefs.getString("draft_body", ""))
acquireCamera()
acquireAudioFocus()
}
}
A NoteEditorActivity példa bemutatja a helyes munkát onPause-szal: a piszkozat mentése SharedPreferences-be apply()-vel, a videófájl felfüggesztése, a kamera és az audiofókusz felszabadítása. Minden hívás könnyű és gyors, nem blokkolja az UI szálat ANR-ig. Figyeljen a sorrendre: a super.onPause() az első sorban hívódik — ez garantálja, hogy a rendszerlogika akkor is végrehajtódik, ha kivétel történik a felhasználói kódban.
onPause — az utolsó pont, ahol a fejlesztő garantáltan elmentheti a felhasználói adatokat, mielőtt az alkalmazást a rendszer elrejti vagy megöli. Az onStop után a rendszer megsemmisítheti a folyamatot memóriahiány esetén anélkül, hogy meghívná onDestroy-t. Az onSaveInstanceState() metódus onPause után hívódik, de a Bundle-je nem hosszú távú tárolásra való — csak a következő onCreate-ig él.
A SharedPreferences aszinkron apply()-vel — az optimális mód kis adatmennyiségek mentésére onPause-ban. Ellentétben a commit()-tal, amely szinkron módon írja az adatokat a lemezre és boolean-t ad vissza, az apply() azonnal elmenti az adatokat a memóriába és ütemezi az aszinkron lemezre írást. Ez kevesebb mint 1 ezredmásodpercet vesz igénybe az UI szálon, szemben a commit() 10–100 ezredmásodpercével.
override fun onPause() {
super.onPause()
// ❌ Rossz: a szinkron írás blokkolja a szálat
// prefs.edit().putInt("score", score).commit()
// ✅ Jó: aszinkron írás
prefs.edit().putInt("score", score).apply()
// Összetett objektumokhoz — gyorsítótárazás ViewModel-ben
viewModel.saveState()
}
Strukturált adatokhoz (SQLite Room-on keresztül) onPause-ban korutinokat használunk lifecycleScope-pal. A ViewModelScope automatikusan lemondja a korutint a ViewModel megsemmisítésekor, megakadályozva az írást egy lezárt adatbázisba. A Room-on keresztüli írás korutinokkal 5–15 ezredmásodpercet vesz igénybe, és nem blokkolja az UI szálat.
// ViewModel-ben:
fun saveDraft(title: String, body: String) {
viewModelScope.launch(Dispatchers.IO) {
noteDao.insert(NoteDraft(title = title, body = body))
}
}
// Activity.onPause-ban:
viewModel.saveDraft(
binding?.titleInput?.text.toString(),
binding?.bodyInput?.text.toString()
)
onPause Fragment-ben akkor hívódik, amikor a Fragment megszűnik aktív lenni, de látható maradhat. Ez akkor történik, amikor: a Fragment-et egy másik Fragment váltja fel FragmentTransaction segítségével; a Fragment megszűnik az aktuális oldal lenni a ViewPager-ben; a Fragmentet tartalmazó Activity onPause-t kap. Az Activity onPause és a Fragment onPause közötti interakció szigorúan hierarchikus: először az Activity kap onPause-t, majd az összes Fragment-je.
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()
}
}
}
A térképekkel való munka sajátossága onPause-ban: a Google Maps és a Yandex Maps jelentős GPU erőforrásokat fogyaszt aktív követési módban (follow mode). Fókuszvesztéskor érdemes kikapcsolni a térkép animációját és csökkenteni a markerek frissítési gyakoriságát, a fókusz visszatérésekor pedig visszaállítani a teljes funkcionalitást. Ez javítja a teljesítményt és csökkenti az energiafogyasztást a képernyők közötti váltáskor.
Az egyik leggyakoribb zavar a kezdő Android-fejlesztők körében — az onPause és onStop közötti különbség meg nem értése. Vizsgáljuk meg az egyes forgatókönyveket és határozzuk meg a helyes metódust.
| Forgatókönyv | onPause | onStop |
|---|---|---|
| Párbeszédablak megnyitása | Meghívódik | Nem hívódik |
| Új Activity megnyitása (nem átlátszó) | Meghívódik | Meghívódik |
| „Kezdőlap” gomb megnyomása | Meghívódik | Meghívódik |
| Képernyő lezárása | Meghívódik | Meghívódik |
| Bejövő hívás | Meghívódik | Meghívódik |
| Átlátszó Activity a jelenlegi felett | Meghívódik | Nem hívódik |
| Split Screen (fél képernyő) | Meghívódik | Nem hívódik |
| PiP (Picture-in-Picture) | Meghívódik | Nem hívódik |
Fő szabály: onPause minden fókuszvesztéskor meghívódik, onStop — csak teljes láthatóságvesztéskor. Ha az Activity látható marad (még részben is), onStop nem hívódik meg. Ez kritikus a Split Screen, PiP és átlátszó Activity módokban — itt onPause/onResume működik, de onStart/onStop nem.
onPause — az életciklus időben legkritikusabb metódusa, mivel blokkolja a következő Activity renderelését. A rendszer megvárja az aktuális Activity onPause-jának befejezését, mielőtt megjelenítené az újat. Ha az onPause több mint 100 ezredmásodpercig tart, a felhasználó késlekedést észlel az átmenetben; ha több mint 5 másodpercig — a rendszer ANR-t jelenít meg.
A Google Android Performance Guide (2025) a következő javaslatokat adja onPause-hoz: ne végezzen hálózati kéréseket — ezeket le kell mondani vagy át kell helyezni WorkManager-be; ne írjon nagy fájlokat lemezre — használjon BufferedWriter-t háttérszálon; ne hajtson végre összetett SQL lekérdezéseket — a Room műveletek legyenek aszinkronok korutinokon keresztül; kerülje az új objektumok létrehozását — a szemétgyűjtés onPause-ban súlyosbítja a késlekedést; használjon apply()-t a commit() helyett SharedPreferences esetén.
override fun onPause() {
super.onPause()
// ❌ Rossz: a HTTP-kérés blokkolja az UI-t
// val response = api.syncSave(data).execute()
// ❌ Rossz: szinkron írás fájlba
// FileOutputStream(file).write(data)
// ✅ Jó: aszinkron mentés
lifecycleScope.launch {
withContext(Dispatchers.IO) {
api.saveData(data)
fileDao.write(data)
}
}
// ✅ Jó: könnyű írás SharedPreferences-be
prefs.edit().putString("key", value).apply()
}
Az onPause profilozása Android Studio Profiler-en keresztül (CPU grafikon) megmutatja a pontos végrehajtási időt. Ha az onPause több mint 100 ms-ig tart, a Profiler sárgával jelöli a metódust, ha több mint 500 ms-ig — pirossal. Az IT Sectr kereskedelmi projektjeiben Macrobenchmark teszteket használunk, amelyek automatikusan ellenőrzik az Activity-k közötti átmenet idejét és jelzik a teljesítményregressziót a CI pipeline-ban.
Még a tapasztalt fejlesztők is követnek el hibákat onPause-ban. Vizsgáljunk meg öt tipikus problémát és azok megoldásait.
A Room DAO meghívása szinkron lekérdezéssel (.executeAsObservable() korutinok nélkül) onPause-ban 10–50 ms-ra blokkolja az UI szálat. Ha ekkor GC vagy versengés történik az adatbázisba írásért, a késlekedés elérheti a 200–500 ms-t. Megoldás: használjon korutinokat Dispatchers.IO-val vagy apply()-t SharedPreferences esetén.
Az onPause nem a figyelők regisztrálásának helye. Ha BroadcastReceiver-t regisztrál onPause-ban, az aktív marad, amikor az Activity már nem látható. Regisztráció csak onStart/onResume-ban történhet, onPause/onStop-ban pedig csak kijelentkezés. Kivétel — Intent-driven API-k, amelyek regisztrációt igényelnek a hívás előtt.
Ha onPause-ban kezeletlen kivétel történik, a rendszer nem hívja meg onStop-ot és onDestroy-t. Az Activity határozatlan állapotban ragad, és az onResume visszatéréskor nem biztos, hogy helyreállítja a felszabadított erőforrásokat. Megoldás: a kritikus műveleteket try/catch blokkba kell helyezni Log.e()-vel történő naplózással.
Nem kell onPause-ban menteni azokat az adatokat, amelyek könnyen helyreállíthatók. Például az API-kérések eredményeit a Room-ban vagy DataStore-ban a beérkezés pillanatában gyorsítótárazza, nem onPause-ban. Csak azt mentse, amit a felhasználó kézzel vitt be és nem tud automatikusan helyreállítani — szöveg a mezőkben, kiválasztott elemek, görgetési pozíció.
A super.onPause()-t meg kell hívni, de az onCreate-től eltérően a hiánya nem okoz azonnali crash-t. A rendszer „megbocsátja” a super elhagyását onPause-ban, de a belső állapotgép helytelen állapotba kerül. A következő onResume hívás nem biztos, hogy helyreállítja a beviteli fókuszt, és az Activity „befagyott” marad. Mindig hívja meg a super.onPause()-t a lehető legkorábban.
Gyakran Ismételt Kérdések
A finish() meghívása onPause-ban azonnal befejezi az Activity-t a metódusból való visszatérés után. Ez helyes forgatókönyv, ha fókuszvesztéskor be kell zárni a képernyőt (például a hitelesítési képernyőt az alkalmazás minimalizálásakor). Azonban a finish() elindítja a teljes befejezési ciklust: onStop → onDestroy, ami késlekedést ad az átmenethez. Csak akkor használja a finish()-t onPause-ban, ha az valóban szükséges.
onPause — a folyamat befejezését túlélő adatok mentésére (piszkozatok SharedPreferences/Room-ban). onSaveInstanceState — az ideiglenes UI állapot mentésére, amely csak a következő onCreate-ig szükséges (görgetési pozíció, kiválasztott lap). Az onSaveInstanceState Bundle-je nem őrződik meg az alkalmazás teljes befejezésekor — csak memóriában létezik. Az onPause adatok lemezre kerülnek és túlélik az újraindítást.
Nem ajánlott. Párbeszédablak vagy felugró ablak megnyitása onPause-ban WindowLeakException-hez vezet, ha az Activity már befejeződött. Ha fókuszvesztéskor értesítést kell megjeleníteni, használja a NotificationManager-t (rendszerértesítések) — ez biztonságos és a felhasználó által várt. Késleltetett műveletekhez használja az AlarmManager-t vagy WorkManager-t.
Az onPause garantáltan meghívódik, mielőtt az Activity megszűnik aktív lenni. Az onStop nem biztos, hogy meghívódik, ha a rendszer megöli a folyamatot a memória felszabadításához — ebben az esetben onDestroy sem hívódik. Az onPause az egyetlen metódus onResume után, amely mindig meghívódik, függetlenül a fókuszvesztés okától. Ezért minden kritikus adatot pontosan onPause-ban mentenek.
Az onPause teszteléséhez Robolectric-ot vagy FragmentScenario-t használunk az AndroidX Test-ből. A FragmentScenario.create() → moveToState(State.STARTED) → moveToState(State.RESUMED) → moveToState(State.STARTED) szekvenciálisan meghívja az onPause-t. Ezután ellenőrizzük, hogy az adatok el lettek-e mentve SharedPreferences-be, vagy hogy a kamera felszabadult-e mock objektumon keresztül. A Robolectric 4.12+ támogatja az onPause/onResume emulációt fizikai eszköz nélkül.
Összefoglalá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