onResume — метод животног циклуса Android-а који се позива када Activity или Fragment изађе у први план и добије фокус уноса. У овом стању екран је спреман за интеракцију са корисником: сви догађаји додира, притисци тастера и гестови се усмеравају ка овој компоненти. onResume је радно стање Activity у којем апликација проводи већину времена. Управо овде се отвара камера, покреће репродукција видеа, започиње препознавање говора и региструју сензорски слушаоци који захтевају ексклузивни приступ. Више о потпуном животном циклусу Activity прочитајте у чланку Activity Lifecycle.
Главно
onResume — трећи метод животног циклуса Activity, позива се после onStart, који сигнализира спремност екрана за потпуну интеракцију са корисником. У овом тренутку Activity се налази на врху стека задатака (back stack), систем му усмерава све догађаје уноса, а апликација може започети било које операције које захтевају активно учешће корисника: видео-позиви, игре, аудио-снимање, цртање на Canvas-у.
onResume улази у живот на предњем плану (foreground lifetime) — период између onResume и onPause. Ово је најактивнији период рада Activity, када апликација троши максимум ресурса: процесор за обраду додира, GPU за рендеровање анимација, камеру и микрофон за видео-захват. Разумевање овог нивоа животног циклуса је кључно за оптимизацију потрошње енергије — ресурси отворени у onResume морају бити одмах затворени у onPause.
Према подацима Google I/O 2025, просечно време које Activity проводи у стању onResume током једне сесије износи 2–5 минута за вести и 15–30 минута за игре и месинџере. Остатак времена Activity се налази у стањима onPause, onStop или onDestroy. То значи да оптимизација управо onResume кода даје највећи добитак у перформансама и трајању батерије.
У Activity метод onResume се позива сваки пут када екран добије фокус уноса — при првом покретању, при повратку из другог Activity, при затварању дијалошког прозора, при откључавању уређаја. Ово је врући метод који се може позвати више пута током сесије, па његова имплементација мора бити максимално лагана.
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", "Повезивање камере није успело", e)
}
}, ContextCompact.getMainExecutor(this))
}
override fun onPause() {
super.onPause()
cameraProvider?.unbindAll()
preview = null
}
}
Пример са CameraX-ом демонстрира класичну употребу onResume/onPause: камера је ексклузивни ресурс који може користити само једна апликација у датом тренутку. Повезивање камере са животним циклусом путем bindToLifecycle аутоматски затвара камеру у onPause, али експлицитни позив unbindAll гарантује тренутно ослобађање. Ово је посебно важно при пребацивању између Activity-ја: камера мора бити ослобођена пре него што други Activity покуша да је отвори.
onResume у Fragment-у се позива након што је Activity које га садржи добило onResume. Међутим, због особености FragmentManager-а и ViewPager-а, тренутак позивања onResume за Fragment може бити одложен у односу на Activity. На пример, Fragment у ViewPager-у са offscreenPageLimit = 1 добија onResume тек када постане текућа страница, а не при покретању 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()
}
}
Провера userVisibleHint у Fragment.onResume је битна за ViewPager: Fragment може добити onResume, али бити скривен суседном страницом (на пример, при анимираном прелазу). У таквим случајевима покретање видеа или биометрије у onResume без провере видљивости доводи до неочекиваног понашања. Од Fragment 1.5.0 препоручује се коришћење FragmentTransaction.setMaxLifecycle() за прецизну контролу животног циклуса фрагмената у ViewPager2.
Програмери често мешају onStart и onResume, постављајући код у неодговарајући метод. Главно правило: onStart — за ресурсе који раде при видљивости; onResume — за ресурсе који захтевају фокус уноса. Размотримо конкретне сценарије и правилан избор метода.
| Операција | Метод | Образложење |
|---|---|---|
| Претплата на геолокацију | onStart / onStop | GPS може радити при делимичној видљивости |
| Отварање камере | onResume / onPause | Камера — ексклузивни ресурс |
| BroadcastReceiver | onStart / onStop | Системски догађаји не захтевају фокус |
| Репродукција видеа | onResume / onPause | Видео мора бити видљив кориснику |
| Bluetooth скенирање | onStart / onStop | Скенирање може ићи у позадини |
| Диктафон (MediaRecorder) | onResume / onPause | Снимање захтева активан UI |
| Сензорски слушаоци | onResume / onPause | Сензори за игре и гестове |
| Ажурирање података | onStart | Свежи подаци потребни при појављивању |
Практично правило: ако операција треба да се прекине при појави дијалошког прозора — користите onResume/onPause. Ако операција може да се настави при делимичном прекривању екрана — користите onStart/onStop. На пример, видео-плејер мора да паузира видео при отварању дијалога (onPause), а геолокација може да настави са ажурирањем (остаје у onStart).
Ексклузивни ресурси — компоненте уређаја које може користити само једна апликација у датом тренутку. Камера, микрофон, видео-излаз (MediaProjection), NFC адаптер у режиму читања, USB уређаји у accessory режиму — сви ови ресурси морају бити отворени у onResume и ослобођени у onPause.
MediaRecorder се користи за снимање аудио и видео записа. Захтев за дозволе и припрема MediaRecorder-а се обавља у onCreate, а почетак снимања — у onResume. Ако корисник пређе на другу апликацију, onPause зауставља снимање, а onResume га наставља. Ово је стандардно понашање за диктафоне и апликације за снимање видеа.
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()
}
Биометријска аутентификација (BiometricPrompt) треба да се позива само када се Activity налази у onResume. Ако је позовете у onCreate или onStart, биометријски дијалог може да се појави пре него што Activity заврши иницијализацију, што ће довести до неисправне обраде резултата. Позивање у onResume гарантује да ће биометријски прозор бити приказан у исправном контексту.
Размотримо три проверена обрасца рада са onResume који се примењују у комерцијалним пројектима: ресетовање тајмера неактивности, ажурирање видљивих података и интеграција са Jetpack Navigation.
У апликацијама са поверљивим подацима (банкарство, медицински картони) onResume се користи за ресетовање тајмера аутоматског изласка. Ако корисник активно интерагује са апликацијом, onResume се позива при сваком прелазу између екрана и тајмер се ресетује. Ако корисник смањи апликацију, onPause зауставља тајмер, а onResume при повратку или га ресетује или захтева поновну аутентификацију.
Листа која треба да приказује актуелне податке при сваком повратку на екран ажурира се у onResume. На пример, ако је корисник креирао нови запис у другом Activity и вратио се назад, onResume поново учитава листу из локалне базе података или из кеша ViewModel-а. Ово обезбеђује конзистентност података без ручног позивања notifyDataSetChanged.
override fun onResume() {
super.onResume()
// ActivityResultLauncher је вратио резултат — ажурирамо листу
viewModel.refreshList()
// Ресетовање тајмера неактивности
inactivityTimer.reset()
}
У Jetpack Navigation onResume фрагмента се позива при сваком повратку на њега кроз назадну навигацију. Ово својство се користи за ресетовање стања UI: скривање тастатуре, чишћење поља за претрагу, ажурирање наслова алатне траке. OnBackPressedCallback у комбинацији са onResume даје потпуну контролу над навигацијом без дуплирања кода.
Често постављана питања
onStart — екран је видљив. onResume — екран је активан и спреман за интеракцију. Замислите: гледате телевизор (onStart), али узимате даљински у руке (onResume). Телевизор је увек видљив, али интеракција почиње тек са даљинским. Ако неко прекрије телевизор завесом — екран престаје да буде видљив (onStop). Ако вам узму даљински — интеракција престаје (onPause), али телевизор је још увек видљив.
onResume се позива сваки пут када Activity добије фокус уноса. Минимални број — једном (при покретању). Максимални зависи од сценарија коришћења: пребацивање између екрана, отварање дијалога, брзо закључавање и откључавање уређаја — сваки такав сценарио позива onResume при повратку на екран.
Камера — ексклузивни ресурс доступан само једној апликацији у датом тренутку. Ако отворите камеру у onCreate или onStart, она ће остати блокирана за друге апликације чак и када је ваша апликација неактивна. onResume гарантује да је камера отворена само када је Activity у првом плану, а onPause је одмах затвара. Ово је стандард Android развоја, утврђен у документацији CameraX и Camera2 API.
Да, onResume може да не наступи ако се Activity прекрије другим Activity одмах након појављивања. На пример, Activity A покреће Activity B у методи onCreate или onStart. У овом случају A добија onStart → onPause → onStop, прескачући onResume. Систем не позива onResume зато што Activity A никада није добило фокус уноса.
У onResume не треба извршавати дуге синхроне операције: учитавање великих података из мреже, сложени SQL упити, обрада слика. Метод onResume ради у UI нити и свако блокирање дуже од 100–200 ms доводи до кашњења одзива интерфејса. Све тешке операције морају бити асинхроне — преко корутина, RxJava или WorkManager-а. Такође се не препоручује позивање finish() у onResume без провере — то може довести до бесконачне петље поновног креирања.
Закључци
Развићемо мобилну апликацију под кључ
IT Sectr креира iOS и Android апликације за стартапе и предузећа од 2017. године. Саветоваћемо вас и предложити најбоље решење.
Прочитајте такође