onPause: wat is het, bewaren van de Activity-status in Android

Auteur: IT Sectr Gepubliceerd: 2026-03-04 Leestijd: 10 min

onPause — is de levenscyclusmethode van Android die wordt aangeroepen wanneer Activity de invoerfocus verliest, maar gedeeltelijk zichtbaar blijft op het scherm. Het systeem roept onPause aan voordat een nieuwe Activity op de voorgrond komt, bij het openen van een dialoogvenster, bij het indrukken van de knop „Recente apps” of bij een inkomend gesprek. Deze methode is het laatste gegarandeerde punt voor het opslaan van gebruikersgegevens, omdat het systeem na onStop en onDestroy het proces kan beëindigen zonder extra aanroepen. Binnen onPause bewaart de ontwikkelaar concepten, pauzeert animaties, geeft de camera vrij en schrijft de huidige UI-status naar SharedPreferences. Lees meer over de volledige Activity-levenscyclus in het artikel Activity Lifecycle.

Belangrijkste

  • onPause — Activity verliest focus, maar blijft zichtbaar; laatste gegarandeerde punt voor gegevensopslag
  • Statusbewaring — in onPause worden kritieke gebruikersgegevens bewaard: concepten, tekst in formulieren, voortgang
  • Bronnen vrijgeven — camera, microfoon, videospeler worden in onPause vrijgegeven voor overdracht aan een andere app
  • Tijdslimiet — onPause moet binnen 100 ms worden voltooid; overschrijding veroorzaakt ANR en vertraagt de overgang
  • SharedPreferences.apply() — asynchroon schrijven in onPause; commit() blokkeert de thread en kan ANR veroorzaken
  • onPause vs onStop — onPause bij gedeeltelijke zichtbaarheid (dialoog), onStop bij volledige verberging (andere Activity)
  • onSaveInstanceState — wordt na onPause aangeroepen om tijdelijke status in Bundle op te slaan

Wat is onPause in Android

onPause — de vierde methode van de Activity-levenscyclus, die wordt aangeroepen wanneer het scherm de invoerfocus verliest, maar gedeeltelijk zichtbaar blijft voor de gebruiker. Dit is een „overgangs”toestand tussen het actieve werk van de app en het verbergen ervan. Het systeem roept onPause aan in de volgende scenario's: openen van een andere Activity (nieuw scherm bedekt het huidige), verschijnen van een dialoogvenster (Dialog, PopupWindow, Snackbar roepen onPause niet aan, maar DialogFragment wel), indrukken van de knop „Recente apps”, inkomend gesprek, indrukken van de aan/uit-knop om het scherm te vergrendelen.

De hoofdtaak van onPause is de app voorbereiden op de mogelijkheid dat deze wordt verborgen of vernietigd. Dit is het laatste punt in de levenscyclus waar de ontwikkelaar er zeker van kan zijn dat zijn code wordt uitgevoerd voordat het systeem verder gaat naar een andere component. Na onPause roept het systeem onStop aan (als Activity volledig wordt verborgen), waarna vernietiging van het proces op elk moment kan plaatsvinden zonder extra meldingen.

Volgens de Android Developers-documentatie (2025) moet onPause zo licht en snel mogelijk zijn. Zolang onPause de controle niet teruggeeft, kan het systeem de volgende Activity niet starten — dit betekent dat de gebruiker een vertraging in de overgang tussen schermen ziet. Google raadt aan onPause in minder dan 100 milliseconden te voltooien en alle langdurige bewerkingen (opslaan in database, schrijven naar schijf) asynchroon uit te voeren via coroutines of apply().

onPause in Activity

In Activity wordt de onPause-methode aangeroepen telkens wanneer het scherm niet langer actief is, maar nog gedeeltelijk kan worden weergegeven. Typisch voorbeeld: de gebruiker opent de app „Kaarten”, drukt op „Locatie delen” en boven de Kaarten opent een systeemdialoog voor het selecteren van een app. De Activity van Kaarten krijgt onPause, maar blijft zichtbaar onder de dialoog. Wanneer de dialoog wordt gesloten, krijgen Kaarten onResume zonder aanroep van onStart (het scherm was niet volledig verborgen).

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

        // Concept van notitie opslaan — asynchroon
        prefs.edit()
            .putString("draft_title", binding?.titleInput?.text.toString())
            .putString("draft_body", binding?.bodyInput?.text.toString())
            .putLong("draft_timestamp", System.currentTimeMillis())
            .apply()

        // Video pauzeren
        binding?.videoPlayer?.pause()

        // Exclusieve bronnen vrijgeven
        releaseCamera()
        releaseAudioFocus()
    }

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

Het voorbeeld NoteEditorActivity demonstreert correct werken met onPause: bewaren van het concept in SharedPreferences via apply(), pauzeren van het videobestand, vrijgeven van de camera en audiofocus. Elke aanroep is licht en snel, zonder de UI-thread voldoende te blokkeren voor ANR. Let op de volgorde: super.onPause() wordt in de eerste regel aangeroepen — dit garandeert dat de systeemlogica wordt uitgevoerd, zelfs bij een uitzondering in de gebruikerscode.

Status bewaren in onPause

onPause — het laatste punt waar de ontwikkelaar gegarandeerd gebruikersgegevens kan opslaan voordat de app wordt verborgen of door het systeem wordt beëindigd. Na onStop kan het systeem het proces vernietigen bij geheugengebrek zonder onDestroy aan te roepen. De methode onSaveInstanceState() wordt na onPause aangeroepen, maar de Bundle ervan is niet bedoeld voor langdurige opslag — deze leeft alleen tot de volgende onCreate.

SharedPreferences met apply()

SharedPreferences met asynchrone apply() — de optimale manier om kleine hoeveelheden gegevens op te slaan in onPause. In tegenstelling tot commit(), die synchroon gegevens naar schijf schrijft en boolean retourneert, slaat apply() onmiddellijk gegevens in het geheugen op en plant het een asynchrone schrijfactie naar schijf. Dit duurt minder dan 1 milliseconde in de UI-thread tegenover 10–100 milliseconden voor commit().

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

    // ❌ Slecht: synchroon schrijven blokkeert thread
    // prefs.edit().putInt("score", score).commit()

    // ✅ Goed: asynchroon schrijven
    prefs.edit().putInt("score", score).apply()

    // Voor complexe objecten — caching in ViewModel
    viewModel.saveState()
}

Room en coroutines

Voor gestructureerde gegevens (SQLite via Room) in onPause worden coroutines met lifecycleScope gebruikt. ViewModelScope annuleert automatisch de coroutine bij vernietiging van de ViewModel, wat schrijven naar een gesloten database voorkomt. Schrijven via Room met coroutines duurt 5–15 milliseconden en blokkeert de UI-thread niet.

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

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

onPause in Fragment

onPause in Fragment wordt aangeroepen wanneer het Fragment niet langer actief is, maar zichtbaar kan blijven. Dit gebeurt wanneer: het Fragment wordt vervangen door een ander Fragment via FragmentTransaction; het Fragment niet langer de huidige pagina in ViewPager is; de Activity die het Fragment bevat onPause krijgt. De interactie tussen onPause van Activity en onPause van Fragment is strikt hiërarchisch: eerst krijgt Activity onPause, dan al zijn Fragmenten.

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

Specificiteit van werken met kaarten in onPause: Google Maps en Yandex Maps verbruiken aanzienlijke GPU-bronnen in de actieve volgmodus (follow mode). Bij focusverlies is het zinvol om de kaartanimatie uit te schakelen en de vernieuwingsfrequentie van markers te verlagen, en bij focushervatting de volledige functionaliteit te herstellen. Dit verbetert de prestaties en vermindert het energieverbruik bij het schakelen tussen schermen.

onPause vs onStop: verschil en scenario's

Een van de meest voorkomende verwarringen bij beginnende Android-ontwikkelaars is het niet begrijpen van het verschil tussen onPause en onStop. Laten we elk scenario bekijken en de juiste methode bepalen.

ScenarioonPauseonStop
Openen van een dialoogvensterAangeroepenNiet aangeroepen
Openen van een nieuwe Activity (niet transparant)AangeroepenAangeroepen
Indrukken van de knop „Home”AangeroepenAangeroepen
Scherm vergrendelenAangeroepenAangeroepen
Inkomend gesprekAangeroepenAangeroepen
Transparante Activity boven huidigeAangeroepenNiet aangeroepen
Split Screen (helft scherm)AangeroepenNiet aangeroepen
PiP (Picture-in-Picture)AangeroepenNiet aangeroepen

Hoofdregel: onPause wordt aangeroepen bij elk focusverlies, onStop — alleen bij volledig verlies van zichtbaarheid. Als Activity zichtbaar blijft (zelfs gedeeltelijk), wordt onStop niet aangeroepen. Dit is cruciaal voor de modi Split Screen, PiP en transparante Activity's — hier werken onPause/onResume, maar onStart/onStop niet.

Timing en prestaties van onPause

onPause — de meest kritieke methode qua tijd in de levenscyclus, omdat deze het renderen van de volgende Activity blokkeert. Het systeem wacht op voltooiing van onPause van de huidige Activity voordat het een nieuwe toont. Als onPause langer dan 100 milliseconden duurt, merkt de gebruiker een vertraging in de overgang; als het langer dan 5 seconden duurt, toont het systeem ANR.

Prestatieaanbevelingen

De Google Android Performance Guide (2025) geeft de volgende aanbevelingen voor onPause: voer geen netwerkverzoeken uit — deze moeten worden geannuleerd of verplaatst naar WorkManager; schrijf geen grote bestanden naar schijf — gebruik BufferedWriter in een achtergrondthread; voer geen complexe SQL-query's uit — Room-bewerkingen moeten asynchroon zijn via coroutines; vermijd het maken van nieuwe objecten — garbage collection in onPause verergert de vertraging; gebruik apply() in plaats van commit() voor SharedPreferences.

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

    // ❌ Slecht: HTTP-verzoek blokkeert UI
    // val response = api.syncSave(data).execute()

    // ❌ Slecht: synchroon schrijven naar bestand
    // FileOutputStream(file).write(data)

    // ✅ Goed: asynchroon opslaan
    lifecycleScope.launch {
        withContext(Dispatchers.IO) {
            api.saveData(data)
            fileDao.write(data)
        }
    }

    // ✅ Goed: licht schrijven naar SharedPreferences
    prefs.edit().putString("key", value).apply()
}

Het profileren van onPause via Android Studio Profiler (CPU-grafiek) toont de exacte uitvoeringstijd. Als onPause meer dan 100 ms duurt, markeert Profiler de methode geel, en meer dan 500 ms — rood. In commerciële projecten van IT Sectr gebruiken we Macrobenchmark-tests die automatisch de overgangstijd tussen Activity's controleren en prestatieregressie signaleren in de CI-pipeline.

Veelvoorkomende fouten in onPause

Zelfs ervaren ontwikkelaars maken fouten in onPause. Laten we vijf typische problemen en hun oplossingen bekijken.

Synchroon schrijven naar de database

Het aanroepen van Room DAO met een synchrone query (.executeAsObservable() zonder coroutines) in onPause blokkeert de UI-thread gedurende 10–50 ms. Als op dat moment GC of concurrentie voor het schrijven naar de database plaatsvindt, kan de vertraging oplopen tot 200–500 ms. Oplossing: gebruik coroutines met Dispatchers.IO of apply() voor SharedPreferences.

Registreren van nieuwe listeners

onPause is niet de plaats voor het registreren van listeners. Als u een BroadcastReceiver registreert in onPause, blijft deze actief wanneer de Activity niet meer zichtbaar is. Registratie mag alleen plaatsvinden in onStart/onResume, en in onPause/onStop — alleen uitschrijven. Uitzondering — Intent-driven API's die registratie vereisen voor aanroep.

Negeren van uitzonderingen

Als er in onPause een onverwerkte uitzondering optreedt, roept het systeem onStop en onDestroy niet aan. De Activity blijft hangen in een onbepaalde toestand en onResume bij terugkeer kan de vrijgegeven bronnen niet correct herstellen. Oplossing: omhul kritieke bewerkingen met try/catch en log via Log.e().

Opslaan van overbodige gegevens

Het is niet nodig om in onPause gegevens op te slaan die gemakkelijk kunnen worden hersteld. Bijvoorbeeld, resultaten van API-verzoeken worden in cache opgeslagen in Room of DataStore op het moment van ontvangst, niet in onPause. Sla alleen op wat de gebruiker handmatig heeft ingevoerd en niet automatisch kan worden hersteld — tekst in velden, geselecteerde elementen, scrollpositie.

Vergeten super.onPause()

super.onPause() moet worden aangeroepen, maar in tegenstelling tot onCreate veroorzaakt het ontbreken ervan geen onmiddellijke crash. Het systeem 'vergeeft' het overslaan van super in onPause, maar de interne toestandsmachine gaat naar een onjuiste toestand. De volgende aanroep van onResume kan de invoerfocus mogelijk niet herstellen en de Activity blijft 'bevroren'. Roep altijd super.onPause() zo vroeg mogelijk aan.

Veelgestelde vragen

Wat gebeurt er als je finish() aanroept in onPause?

Het aanroepen van finish() in onPause beëindigt de Activity onmiddellijk na terugkeer uit de methode. Dit is een correct scenario als bij focusverlies het scherm moet worden gesloten (bijvoorbeeld het authenticatiescherm bij het minimaliseren van de app). Echter, finish() start de volledige beëindigingscyclus: onStop → onDestroy, wat vertraging toevoegt aan de overgang. Gebruik finish() in onPause alleen wanneer het echt nodig is.

Waarin verschilt onPause van onSaveInstanceState?

onPause — voor het opslaan van gegevens die het beëindigen van het proces moeten overleven (concepten in SharedPreferences/Room). onSaveInstanceState — voor het opslaan van tijdelijke UI-status die alleen nodig is tot de volgende onCreate (scrollpositie, geselecteerd tabblad). De Bundle van onSaveInstanceState wordt niet bewaard bij volledige beëindiging van de app — deze bestaat alleen in het geheugen. onPause-gegevens worden op schijf opgeslagen en overleven een herstart.

Kan een dialoogvenster worden geopend in onPause?

Niet aanbevolen. Het openen van een dialoog of pop-upvenster in onPause leidt tot WindowLeakException als de Activity al is beëindigd. Als u een melding moet tonen bij focusverlies, gebruik dan NotificationManager (systeemmeldingen) — dit is veilig en wordt verwacht door de gebruiker. Voor uitgestelde acties gebruikt u AlarmManager of WorkManager.

Waarom is onPause een gegarandeerde opslagplaats en onStop niet?

onPause wordt gegarandeerd aangeroepen voordat Activity niet langer actief is. onStop wordt mogelijk niet aangeroepen als het systeem het proces beëindigt om geheugen vrij te maken — in dat geval wordt onDestroy ook niet aangeroepen. onPause is de enige methode na onResume die altijd wordt aangeroepen, ongeacht de reden van focusverlies. Daarom worden alle kritieke gegevens precies in onPause opgeslagen.

Hoe test je onPause in unittesten?

Voor het testen van onPause wordt Robolectric of FragmentScenario van AndroidX Test gebruikt. FragmentScenario.create() → moveToState(State.STARTED) → moveToState(State.RESUMED) → moveToState(State.STARTED) roept sequentieel onPause aan. Vervolgens wordt gecontroleerd of de gegevens zijn opgeslagen in SharedPreferences of dat de camera is vrijgegeven via een mock-object. Robolectric 4.12+ ondersteunt emulatie van onPause/onResume zonder fysiek apparaat.

Samenvatting

  • onPause — Activity verliest invoerfocus, maar blijft gedeeltelijk zichtbaar; laatste gegarandeerde punt voor gegevensopslag
  • Opslag — SharedPreferences.apply() of Room via coroutines; commit() en synchrone bewerkingen zijn verboden
  • Bronnen vrijgeven — camera, audiofocus, videospeler worden in onPause vrijgegeven voor een andere app
  • Limiet 100 ms — onPause blokkeert het renderen van de volgende Activity; overschrijding veroorzaakt ANR
  • onPause vs onStop — onPause bij focusverlies (zichtbaarheid behouden), onStop bij volledige verberging
  • Fragment.onPause — hiërarchische aanroep na Activity.onPause; specificiteit voor kaarten en ViewPager
  • Typische fouten — synchroon schrijven, registreren van listeners, negeren van try/catch, overbodige opslag
  • super.onPause() — zo vroeg mogelijk aanroepen; overslaan veroorzaakt geen crash, maar beschadigt de toestandsmachine

We ontwikkelen een mobiele applicatie turnkey

IT Sectr creëert sinds 2017 iOS- en Android-applicaties voor startups en bedrijven. We adviseren u en stellen de beste oplossing voor.

Bespreek het project

Lees ook