onPause: mi ez, az Activity állapotának mentése Androidban

Szerző: IT Sectr Megjelenés: 2026-03-04 Olvasási idő: 10 perc

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 elveszíti a fókuszt, de látható marad; az utolsó garantált adatmentési pont
  • Állapotmentés — onPause-ban mentik a kritikus felhasználói adatokat: piszkozatok, űrlapok szövege, haladás
  • Erőforrások felszabadítása — kamera, mikrofon, videolejátszó onPause-ban szabadul fel más alkalmazás számára
  • Időkorlát — onPause-nak 100 ms-on belül be kell fejeződnie; túllépés ANR-t okoz és késlelteti az átmenetet
  • SharedPreferences.apply() — aszinkron írás onPause-ban; a commit() blokkolja a szálat és ANR-t okozhat
  • onPause vs onStop — onPause részleges láthatóságnál (párbeszédablak), onStop teljes elrejtésnél (másik Activity)
  • onSaveInstanceState — onPause után hívódik az ideiglenes állapot Bundle-be mentéséhez

Mi az onPause Androidban

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.

onPause Activity-ben

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

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

        // 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.

Állapotmentés onPause-ban

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.

SharedPreferences apply()-vel

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.

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

Room és korutinok

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.

kotlin
// 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

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.

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

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.

onPause vs onStop: különbség és forgatókönyvek

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önyvonPauseonStop
Párbeszédablak megnyitásaMeghívódikNem hívódik
Új Activity megnyitása (nem átlátszó)MeghívódikMeghívódik
„Kezdőlap” gomb megnyomásaMeghívódikMeghívódik
Képernyő lezárásaMeghívódikMeghívódik
Bejövő hívásMeghívódikMeghívódik
Átlátszó Activity a jelenlegi felettMeghívódikNem hívódik
Split Screen (fél képernyő)MeghívódikNem hívódik
PiP (Picture-in-Picture)MeghívódikNem 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.

Az onPause időzítése és teljesítménye

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.

Teljesítményre vonatkozó javaslatok

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.

kotlin
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.

Gyakori hibák onPause-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.

Szinkron írás az adatbázisba

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.

Új figyelők regisztrálása

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.

Kivételek figyelmen kívül hagyása

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.

Túl sok adat mentése

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ó.

Elfelejtett super.onPause()

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

Mi történik, ha finish()-t hívunk onPause-ban?

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.

Miben különbözik az onPause az onSaveInstanceState-tól?

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.

Lehet párbeszédablakot nyitni onPause-ban?

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.

Miért az onPause a garantált mentési hely, és miért nem az onStop?

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.

Hogyan teszteljük az onPause-t egységtesztekkel?

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

  • onPause — az Activity elveszíti a beviteli fókuszt, de részben látható marad; az utolsó garantált adatmentési pont
  • Mentés — SharedPreferences.apply() vagy Room korutinokon keresztül; a commit() és a szinkron műveletek tilosak
  • Erőforrások felszabadítása — kamera, audiofókusz, videolejátszó onPause-ban szabadul fel más alkalmazás számára
  • 100 ms korlát — onPause blokkolja a következő Activity renderelését; a korlát túllépése ANR-t okoz
  • onPause vs onStop — onPause fókuszvesztéskor (láthatóság megmarad), onStop teljes elrejtéskor
  • Fragment.onPause — hierarchikus hívás Activity.onPause után; specifikum térképekhez és ViewPager-hez
  • Tipikus hibák — szinkron írás, figyelők regisztrálása, try/catch figyelmen kívül hagyása, túlzott mentés
  • super.onPause() — a lehető leghamarabb hívja meg; elhagyása nem okoz crash-t, de tönkreteszi az állapotgépet

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.

Projekt megbeszélése

Olvassa el is