onResume — je metoda životního cyklu Androidu, která je volána, když se Activity nebo Fragment dostane do popředí a získá fokus vstupu. V tomto stavu je obrazovka připravena k interakci s uživatelem: všechny události dotyku, stisky kláves a gesta jsou směrovány k této komponentě. onResume je pracovní stav Activity, ve kterém aplikace tráví většinu času. Právě zde se otevírá kamera, spouští přehrávání videa, začíná rozpoznávání řeči a registrují se senzorové posluchače vyžadující exkluzivní přístup. Více o úplném životním cyklu Activity si přečtěte v článku Activity Lifecycle.
Hlavní body
onResume — třetí metoda životního cyklu Activity, volaná po onStart, která signalizuje připravenost obrazovky k plné interakci s uživatelem. V tomto okamžiku je Activity na vrcholu zásobníku úkolů (back stack), systém k němu směruje všechny vstupní události a aplikace může zahájit jakékoli operace vyžadující aktivní účast uživatele: videohovory, hry, záznam zvuku, kreslení na Canvas.
onResume je součástí života v popředí (foreground lifetime) — období mezi onResume a onPause. Toto je nejaktivnější období práce Activity, kdy aplikace spotřebovává maximum prostředků: procesor pro zpracování dotyků, GPU pro vykreslování animací, kameru a mikrofon pro videozáznam. Pochopení této úrovně životního cyklu je klíčové pro optimalizaci spotřeby energie — prostředky otevřené v onResume musí být okamžitě uzavřeny v onPause.
Podle údajů Google I/O 2025 je průměrná doba, kterou Activity stráví ve stavu onResume během jedné relace, 2–5 minut u zpravodajských aplikací a 15–30 minut u her a messengerů. Po zbytek času je Activity ve stavech onPause, onStop nebo onDestroy. To znamená, že optimalizace právě kódu onResume přináší největší zisk ve výkonu a výdrži baterie.
V Activity je metoda onResume volána pokaždé, když obrazovka získá fokus vstupu — při prvním spuštění, při návratu z jiného Activity, při zavření dialogového okna, při odemčení zařízení. Je to horká metoda, která může být volána mnohokrát během relace, a její implementace by měla být co nejlehčí.
class CameraActivity : AppCompatActivity() {
private var cameraProvider: ProcessCameraProvider? = null
private var preview: Preview? = null
override fun onResume() {
super.onResume()
val cameraProviderFuture = ProcessCameraProvider.getInstance(this)
cameraProviderFuture.addListener({
cameraProvider = cameraProviderFuture.get()
val cameraSelector = CameraSelector.DEFAULT_BACK_CAMERA
preview = Preview.Builder().build().also {
it.setSurfaceProvider(binding?.viewFinder?.surfaceProvider)
}
try {
cameraProvider?.unbindAll()
cameraProvider?.bindToLifecycle(
this, cameraSelector, preview
)
} catch (e: Exception) {
Log.e("Camera", "Nepodařilo se svázat kameru", e)
}
}, ContextCompact.getMainExecutor(this))
}
override fun onPause() {
super.onPause()
cameraProvider?.unbindAll()
preview = null
}
}
Příklad s CameraX demonstruje klasické použití onResume/onPause: kamera je exkluzivní prostředek, který může v daném okamžiku používat pouze jedna aplikace. Propojení kamery s životním cyklem prostřednictvím bindToLifecycle automaticky zavírá kameru v onPause, ale explicitní volání unbindAll zaručuje okamžité uvolnění. To je zvláště důležité při přepínání mezi aktivitami: kamera musí být uvolněna dříve, než se ji jiná Activity pokusí otevřít.
onResume ve Fragmentu je voláno poté, co obsahující Activity obdrželo onResume. Kvůli specifikům FragmentManageru a ViewPageru však může být okamžik volání onResume pro Fragment zpožděn vůči Activity. Například Fragment ve ViewPageru s offscreenPageLimit = 1 obdrží onResume až když se stane aktuální stránkou, nikoli při startu Activity.
class VideoPlayerFragment : Fragment() {
private var exoPlayer: ExoPlayer? = null
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
super.onViewCreated(view, savedInstanceState)
exoPlayer = ExoPlayer.Builder(requireContext()).build()
binding?.playerView?.player = exoPlayer
}
override fun onResume() {
super.onResume()
exoPlayer?.play()
if (userVisibleHint) {
startBiometricAuth()
}
}
override fun onPause() {
exoPlayer?.pause()
stopBiometricAuth()
super.onPause()
}
}
Kontrola userVisibleHint ve Fragment.onResume je relevantní pro ViewPager: Fragment může obdržet onResume, ale být skryt sousední stránkou (například při animovaném přechodu). V takových případech spuštění videa nebo biometrie v onResume bez kontroly viditelnosti povede k neočekávanému chování. Od Fragmentu 1.5.0 se doporučuje používat FragmentTransaction.setMaxLifecycle() pro přesnou kontrolu životního cyklu fragmentů ve ViewPager2.
Vývojáři často zaměňují onStart a onResume a umísťují kód do nesprávné metody. Hlavní pravidlo: onStart — pro prostředky pracující při viditelnosti; onResume — pro prostředky vyžadující fokus vstupu. Podívejme se na konkrétní scénáře a správný výběr metody.
| Operace | Metoda | Odůvodnění |
|---|---|---|
| Předplatné geolokace | onStart / onStop | GPS může pracovat při částečné viditelnosti |
| Otevření kamery | onResume / onPause | Kamera — exkluzivní prostředek |
| BroadcastReceiver | onStart / onStop | Systémové události nevyžadují fokus |
| Přehrávání videa | onResume / onPause | Video musí být pro uživatele viditelné |
| Bluetooth skenování | onStart / onStop | Skenování může pokračovat na pozadí |
| Diktátor (MediaRecorder) | onResume / onPause | Nahrávání vyžaduje aktivní UI |
| Senzorové posluchače | onResume / onPause | Snímače pro hry a gesta |
| Aktualizace dat | onStart | Čerstvá data potřebná při zobrazení |
Praktické pravidlo: pokud má být operace přerušena při zobrazení dialogového okna — použijte onResume/onPause. Pokud může operace pokračovat při částečném zakrytí obrazovky — použijte onStart/onStop. Například přehrávač videa by měl pozastavit video při otevření dialogu (onPause), zatímco geolokace může pokračovat v aktualizaci (zůstává v onStart).
Exkluzivní prostředky jsou součásti zařízení, které může v daném okamžiku používat pouze jedna aplikace. Kamera, mikrofon, video výstup (MediaProjection), NFC adaptér v režimu čtení, USB zařízení v režimu accessory — všechny tyto prostředky musí být otevřeny v onResume a uvolněny v onPause.
MediaRecorder se používá pro záznam zvuku a videa. Žádost o oprávnění a příprava MediaRecorderu se provádí v onCreate a spuštění nahrávání v onResume. Pokud uživatel přepne do jiné aplikace, onPause pozastaví nahrávání a onResume jej obnoví. Toto je standardní chování pro diktafony a aplikace pro záznam videa.
private var mediaRecorder: MediaRecorder? = null
private var isRecording = false
override fun onResume() {
super.onResume()
if (isRecording) {
mediaRecorder?.resume()
}
}
override fun onPause() {
if (isRecording) {
mediaRecorder?.pause()
}
super.onPause()
}
Biometrická autentizace (BiometricPrompt) by měla být volána pouze když je Activity v onResume. Pokud ji zavoláte v onCreate nebo onStart, biometrický dialog se může objevit dříve, než Activity dokončí inicializaci, což povede k nesprávnému zpracování výsledku. Volání v onResume zaručuje, že biometrické okno bude zobrazeno ve správném kontextu.
Podívejme se na tři osvědčené vzory práce s onResume, které se používají v komerčních projektech: resetování časovače neaktivity, aktualizace viditelných dat a integrace s Jetpack Navigation.
V aplikacích s důvěrnými daty (bankovnictví, lékařské karty) se onResume používá k resetování časovače automatického odhlášení. Pokud uživatel aktivně interaguje s aplikací, onResume je volán při každém přechodu mezi obrazovkami a časovač se resetuje. Pokud uživatel aplikaci minimalizuje, onPause zastaví časovač a onResume při návratu jej buď resetuje, nebo požádá o opětovnou autentizaci.
Seznam, který by měl zobrazovat aktuální data při každém návratu na obrazovku, je aktualizován v onResume. Například pokud uživatel vytvořil nový záznam v jiné Activity a vrátil se zpět, onResume znovu načte seznam z lokální databáze nebo z mezipaměti ViewModel. To zajišťuje konzistenci dat bez ručního volání notifyDataSetChanged.
override fun onResume() {
super.onResume()
// ActivityResultLauncher vrátil výsledek — aktualizujeme seznam
viewModel.refreshList()
// Resetování časovače neaktivity
inactivityTimer.reset()
}
V Jetpack Navigation je onResume fragmentu volán při každém návratu k němu prostřednictvím zpětné navigace. Tato vlastnost se používá k resetování stavu UI: skrytí klávesnice, vyčištění vyhledávacích polí, aktualizace názvu panelu nástrojů. OnBackPressedCallback v kombinaci s onResume poskytuje plnou kontrolu nad navigací bez duplikace kódu.
Často kladené otázky
onStart — obrazovka je viditelná. onResume — obrazovka je aktivní a připravená k interakci. Představte si: díváte se na televizi (onStart), ale berete ovladač do ruky (onResume). Televize je vždy viditelná, ale interakce začíná až s ovladačem. Pokud někdo zakryje televizi závěsem — obrazovka přestane být viditelná (onStop). Pokud vám ovladač vezmou — interakce končí (onPause), ale televize je stále viditelná.
onResume je volán pokaždé, když Activity získá fokus vstupu. Minimální počet — jednou (při spuštění). Maximální počet závisí na scénářích použití: přepínání mezi obrazovkami, otevírání dialogů, rychlé zamykání a odemykání zařízení — každý takový scénář volá onResume při návratu na obrazovku.
Kamera — exkluzivní prostředek dostupný pouze jedné aplikaci v daném okamžiku. Pokud kameru otevřete v onCreate nebo onStart, zůstane blokovaná pro ostatní aplikace, i když je vaše aplikace neaktivní. onResume zaručuje, že kamera je otevřená pouze když je Activity v popředí, a onPause ji okamžitě zavírá. Toto je standard vývoje pro Android, zakotvený v dokumentaci CameraX a Camera2 API.
Ano, onResume nemusí nastat, pokud je Activity překryto jinou Activity ihned po objevení. Například Activity A spouští Activity B v metodě onCreate nebo onStart. V tomto případě A obdrží onStart → onPause → onStop, přičemž přeskočí onResume. Systém nevolá onResume, protože Activity A nikdy nezískalo fokus vstupu.
V onResume by se neměly provádět dlouhé synchronní operace: načítání velkých dat ze sítě, složité SQL dotazy, zpracování obrázků. Metoda onResume běží v UI vlákně a jakékoli blokování delší než 100–200 ms vede ke zpoždění odezvy rozhraní. Všechny těžké operace by měly být asynchronní — pomocí korutin, RxJava nebo WorkManageru. Také se nedoporučuje volat finish() v onResume bez kontroly — to může vést k nekonečné smyčce znovuvytváření.
Shrnutí
Vyvineme mobilní aplikaci na klíč
IT Sectr vytváří aplikace pro iOS a Android pro startupy a podniky od roku 2017. Poradíme vám a navrhneme nejlepší řešení.
Přečtěte si také