onPause — är Android-livscykelmetoden som anropas när Activity förlorar inmatningsfokus men förblir delvis synligt på skärmen. Systemet anropar onPause innan ett nytt Activity kommer i förgrunden, vid öppnande av en dialogruta, vid tryckning på knappen “Senaste appar” eller vid ett inkommande samtal. Denna metod — den sista garanterade punkten för att spara användardata, eftersom systemet efter onStop och onDestroy kan avsluta processen utan ytterligare anrop. Inuti onPause sparar utvecklaren utkast, pausar animationer, frigör kameran och skriver det aktuella UI-tillståndet till SharedPreferences. Mer om Activitys fulla livscykel läs i artikeln Activity Lifecycle.
Huvudpunkter
onPause — den fjärde metoden i Activitys livscykel, som anropas när skärmen förlorar inmatningsfokus men förblir delvis synlig för användaren. Detta är ett “övergångs”tillstånd mellan appens aktiva arbete och dess döljning. Systemet anropar onPause i följande scenarier: öppnande av ett annat Activity (ny skärm täcker den aktuella), uppdykande av en dialogruta (Dialog, PopupWindow, Snackbar anropar inte onPause, men DialogFragment gör det), tryckning på knappen “Senaste appar”, inkommande samtal, tryckning på knappen “Ström” för att låsa skärmen.
Huvuduppgiften för onPause — förbereda appen för möjligheten att den kan döljas eller förstöras. Detta är den sista punkten i livscykeln där utvecklaren kan vara säker på att hans kod kommer att exekveras innan systemet fortsätter övergången till en annan komponent. Efter onPause anropar systemet onStop (om Activity döljs helt), varefter förstöring av processen kan ske när som helst utan ytterligare meddelanden.
Enligt Android Developers-dokumentationen (2025) måste onPause vara så lätt och snabb som möjligt. Så länge onPause inte återlämnar kontrollen kan systemet inte starta nästa Activity — detta innebär att användaren ser en fördröjning i övergången mellan skärmar. Google rekommenderar att onPause slutförs inom mindre än 100 millisekunder och att alla långvariga operationer (spara i databas, skriva till disk) utförs asynkront via koroutiner eller apply().
I Activity anropas onPause-metoden varje gång skärmen upphör att vara aktiv, men kan fortsätta att visas delvis. Typiskt exempel: användaren öppnar appen “Kartor”, trycker på “Dela plats” och ovanför Kartorna öppnas en systemdialog för att välja app. Kartornas Activity får onPause, men förblir synligt under dialogen. När dialogen stängs får Kartorna onResume utan anrop av onStart (skärmen var inte helt dold).
class NoteEditorActivity : AppCompatActivity() {
private var binding: ActivityNoteEditorBinding? = null
private val prefs by lazy {
getSharedPreferences("note_drafts", Context.MODE_PRIVATE)
}
override fun onPause() {
super.onPause()
// Sparar anteckningsutkastet — asynkront
prefs.edit()
.putString("draft_title", binding?.titleInput?.text.toString())
.putString("draft_body", binding?.bodyInput?.text.toString())
.putLong("draft_timestamp", System.currentTimeMillis())
.apply()
// Pausar videon
binding?.videoPlayer?.pause()
// Frigör exklusiva resurser
releaseCamera()
releaseAudioFocus()
}
override fun onResume() {
super.onResume()
// Återställer utkastet
binding?.titleInput?.setText(prefs.getString("draft_title", ""))
binding?.bodyInput?.setText(prefs.getString("draft_body", ""))
acquireCamera()
acquireAudioFocus()
}
}
Exemplet NoteEditorActivity demonstrerar korrekt arbete med onPause: spara utkastet i SharedPreferences via apply(), pausa videofilen, frigöra kameran och ljudfokus. Varje anrop — lätt och snabbt, utan att blockera UI-tråden tillräckligt för ANR. Observera ordningen: super.onPause() anropas på första raden — detta garanterar att systemlogiken exekveras även vid ett undantag i användarkoden.
onPause — den sista punkten där utvecklaren garanterat kan spara användardata innan appen döljs eller dödas av systemet. Efter onStop kan systemet förstöra processen vid minnesbrist utan att anropa onDestroy. Metoden onSaveInstanceState() anropas efter onPause, men dess Bundle är inte avsedd för långtidslagring — den lever bara till nästa onCreate.
SharedPreferences med asynkron apply() — det optimala sättet att spara små datamängder i onPause. Till skillnad från commit(), som synkront skriver data till disk och returnerar boolean, sparar apply() omedelbart data i minnet och schemalägger asynkron skrivning till disk. Detta tar mindre än 1 millisekund i UI-tråden jämfört med 10–100 millisekunder för commit().
override fun onPause() {
super.onPause()
// ❌ Dåligt: synkron skrivning blockerar tråden
// prefs.edit().putInt("score", score).commit()
// ✅ Bra: asynkron skrivning
prefs.edit().putInt("score", score).apply()
// För komplexa objekt — cachning i ViewModel
viewModel.saveState()
}
För strukturerad data (SQLite via Room) i onPause används koroutiner med lifecycleScope. ViewModelScope avbryter automatiskt koroutinen vid förstöring av ViewModel, vilket förhindrar skrivning till en stängd databas. Skrivning via Room med koroutiner tar 5–15 millisekunder och blockerar inte UI-tråden.
// I ViewModel:
fun saveDraft(title: String, body: String) {
viewModelScope.launch(Dispatchers.IO) {
noteDao.insert(NoteDraft(title = title, body = body))
}
}
// I Activity.onPause:
viewModel.saveDraft(
binding?.titleInput?.text.toString(),
binding?.bodyInput?.text.toString()
)
onPause i Fragment anropas när Fragmentet upphör att vara aktivt, men kan förbli synligt. Detta händer när: Fragmentet ersätts av ett annat Fragment via FragmentTransaction; Fragmentet upphör att vara den aktuella sidan i ViewPager; Activity som innehåller Fragmentet får onPause. Interaktionen mellan onPause för Activity och onPause för Fragment är strikt hierarkisk: först får Activity onPause, sedan alla dess Fragment.
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()
}
}
}
Specificitet för arbete med kartor i onPause: Google Maps och Yandex Maps förbrukar betydande GPU-resurser i aktivt följningsläge (follow mode). Vid fokusförlust är det vettigt att inaktivera kartanimationen och minska uppdateringsfrekvensen för markörer, och vid fokusåterkomst — återställa full funktionalitet. Detta förbättrar prestandan och minskar energiförbrukningen vid växling mellan skärmar.
En av de vanligaste förvirringarna bland nybörjarutvecklare inom Android — att inte förstå skillnaden mellan onPause och onStop. Låt oss undersöka varje scenario och bestämma rätt metod.
| Scenario | onPause | onStop |
|---|---|---|
| Öppna en dialogruta | Anropas | Anropas inte |
| Öppna ett nytt Activity (inte transparent) | Anropas | Anropas |
| Trycka på knappen “Hem” | Anropas | Anropas |
| Låsa skärmen | Anropas | Anropas |
| Inkommande samtal | Anropas | Anropas |
| Transparent Activity ovanför aktuellt | Anropas | Anropas inte |
| Split Screen (halva skärmen) | Anropas | Anropas inte |
| PiP (Picture-in-Picture) | Anropas | Anropas inte |
Huvudregel: onPause anropas vid varje fokusförlust, onStop — endast vid fullständig förlust av synlighet. Om Activity förblir synligt (även delvis), anropas inte onStop. Detta är kritiskt för lägena Split Screen, PiP och transparenta Activity — här fungerar onPause/onResume, men onStart/onStop inte.
onPause — den mest tidskritiska metoden i livscykeln, eftersom den blockerar renderingen av nästa Activity. Systemet väntar på att onPause för det aktuella Activity ska slutföras innan det visar ett nytt. Om onPause tar längre tid än 100 millisekunder märker användaren en fördröjning i övergången; om längre än 5 sekunder — visar systemet ANR.
Google Android Performance Guide (2025) ger följande rekommendationer för onPause: utför inte nätverksförfrågningar — de bör avbrytas eller flyttas till WorkManager; skriv inte stora filer till disk — använd BufferedWriter i en bakgrundstråd; utför inte komplexa SQL-frågor — Room-operationer bör vara asynkrona via koroutiner; undvik att skapa nya objekt — skräpinsamling i onPause förvärrar fördröjningen; använd apply() istället för commit() för SharedPreferences.
override fun onPause() {
super.onPause()
// ❌ Dåligt: HTTP-förfrågan blockerar UI
// val response = api.syncSave(data).execute()
// ❌ Dåligt: synkron skrivning till fil
// FileOutputStream(file).write(data)
// ✅ Bra: asynkron lagring
lifecycleScope.launch {
withContext(Dispatchers.IO) {
api.saveData(data)
fileDao.write(data)
}
}
// ✅ Bra: lätt skrivning till SharedPreferences
prefs.edit().putString("key", value).apply()
}
Profilering av onPause via Android Studio Profiler (CPU-graf) visar den exakta exekveringstiden. Om onPause tar mer än 100 ms markerar Profiler metoden med gult, och mer än 500 ms — med rött. I kommersiella projekt hos IT Sectr använder vi Macrobenchmark-tester som automatiskt kontrollerar övergångstiden mellan Activity och signalerar prestandaregression i CI-pipelinen.
Även erfarna utvecklare gör misstag i onPause. Låt oss undersöka fem typiska problem och deras lösningar.
Anrop av Room DAO med en synkron fråga (.executeAsObservable() utan koroutiner) i onPause blockerar UI-tråden i 10–50 ms. Om GC eller konkurrens om skrivning till databasen inträffar samtidigt kan fördröjningen nå 200–500 ms. Lösning: använd koroutiner med Dispatchers.IO eller apply() för SharedPreferences.
onPause är inte platsen för att registrera lyssnare. Om du registrerar en BroadcastReceiver i onPause förblir den aktiv när Activity inte längre är synligt. Registrering bör endast ske i onStart/onResume och i onPause/onStop — endast avregistrering. Undantag — Intent-drivna API:er som kräver registrering före anrop.
Om ett ohanterat undantag inträffar i onPause anropar systemet inte onStop och onDestroy. Activity fryser i ett obestämt tillstånd och onResume vid återkomst kan inte återställa frigjorda resurser korrekt. Lösning: omge kritiska operationer med try/catch med loggning via Log.e().
Det är inte nödvändigt att spara i onPause data som enkelt kan återställas. Till exempel cachas resultat av API-förfrågningar i Room eller DataStore vid mottagningstillfället, inte i onPause. Spara endast vad användaren har matat in manuellt och inte kan återställa automatiskt — text i fält, valda element, scrollposition.
super.onPause() bör anropas, men till skillnad från onCreate orsakar frånvaron ingen omedelbar krasch. Systemet “förlåter” utelämnandet av super i onPause, men den interna tillståndsmaskinen går in i ett felaktigt tillstånd. Nästa anrop av onResume kan inte återställa inmatningsfokus och Activity förblir “fruset”. Anropa alltid super.onPause() så tidigt som möjligt.
Vanliga frågor
Anrop av finish() i onPause avslutar Activity omedelbart efter återkomst från metoden. Detta är ett korrekt scenario om skärmen måste stängas vid fokusförlust (till exempel auktoriseringsskärmen vid minimering av appen). Dock startar finish() den fulla avslutningscykeln: onStop → onDestroy, vilket lägger till fördröjning till övergången. Använd finish() i onPause endast när det verkligen är nödvändigt.
onPause — för att spara data som måste överleva processavslut (utkast i SharedPreferences/Room). onSaveInstanceState — för att spara temporärt UI-tillstånd som endast behövs till nästa onCreate (scrollposition, vald flik). Bundlet i onSaveInstanceState sparas inte vid fullständig appavslutning — det finns endast i minnet. onPause-data sparas på disk och överlever omstart.
Rekommenderas inte. Öppning av en dialog eller popup-fönster i onPause leder till WindowLeakException om Activity redan är avslutat. Om du behöver visa ett meddelande vid fokusförlust, använd NotificationManager (systemmeddelanden) — detta är säkert och förväntat av användaren. För fördröjda åtgärder, använd AlarmManager eller WorkManager.
onPause anropas garanterat innan Activity upphör att vara aktivt. onStop kanske inte anropas om systemet dödar processen för att frigöra minne — i detta fall anropas inte heller onDestroy. onPause är den enda metoden efter onResume som alltid anropas, oavsett orsaken till fokusförlusten. Därför sparas alla kritiska data just i onPause.
För testning av onPause används Robolectric eller FragmentScenario från AndroidX Test. FragmentScenario.create() → moveToState(State.STARTED) → moveToState(State.RESUMED) → moveToState(State.STARTED) anropar sekventiellt onPause. Därefter kontrolleras om data har sparats i SharedPreferences eller om kameran har frigjorts via ett mock-objekt. Robolectric 4.12+ stöder emulering av onPause/onResume utan fysisk enhet.
Sammanfattning
Vi utvecklar en mobil applikation nyckelfärdigt
IT Sectr skapar iOS- och Android-applikationer för startups och företag sedan 2017. Vi ger dig råd och föreslår den bästa lösningen.
Läs också