onResume — основи, взаємодія з користувачем в Android

Автор: IT Sectr Опубліковано: 2026-03-04 Час читання: 10 хв

onResume — це метод життєвого циклу Android, який викликається, коли Activity або Fragment виходить на передній план і отримує фокус введення. У цьому стані екран готовий до взаємодії з користувачем: всі події дотику, натискання клавіш і жести спрямовуються цьому компоненту. onResume — робочий стан Activity, в якому застосунок проводить більшу частину часу. Саме тут відкривають камеру, запускають відтворення відео, починають розпізнавання мови та реєструють сенсорні слухачі, що потребують монопольного доступу. Докладніше про повний життєвий цикл Activity читайте в статті Activity Lifecycle.

Головне

  • onResume — Activity на передньому плані з фокусом введення; викликається після onStart або після повернення з діалогового вікна
  • Монопольні ресурси — камеру, мікрофон, відеозахоплення відкривають в onResume і закривають в onPause
  • Пара onResume/onPause — ресурси, що потребують повного фокусу, керуються цією парою; реєструються в onResume, звільняються в onPause
  • onResume vs onStart — onStart = видимість, onResume = взаємодія; діалог перекриває onResume, але не onStart
  • Таймінги — onResume має бути швидким; тривалі операції тут затримують відгук інтерфейсу
  • Fragment.onResume — викликається після Activity.onResume, коли Fragment готовий до взаємодії
  • onResume в Jetpack — lifecycleScope та LiveData використовують onResume для автоматичного керування підписками

Основи методу onResume в Android

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-коду дає найбільший виграш у продуктивності та часі роботи від батареї.

onResume в Activity

В Activity метод onResume викликається щоразу, коли екран отримує фокус введення — при першому запуску, при поверненні з іншої Activity, при закритті діалогового вікна, при розблокуванні пристрою. Це «гарячий» метод, який може викликатися багато разів за сесію, і його реалізація має бути максимально легкою.

kotlin
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", "Failed to bind camera", e)
            }
        }, ContextCompact.getMainExecutor(this))
    }

    override fun onPause() {
        super.onPause()
        cameraProvider?.unbindAll()
        preview = null
    }
}

Приклад з CameraX демонструє класичне використання onResume/onPause: камера — монопольний ресурс, який може використовувати лише один застосунок у момент часу. Прив’язка камери до життєвого циклу через bindToLifecycle автоматично закриває камеру в onPause, але явний виклик unbindAll гарантує негайне звільнення. Це особливо важливо при перемиканні між Activity: камера має бути звільнена до того, як інша Activity спробує її відкрити.

onResume у Fragment

onResume у Fragment викликається після того, як Activity, що його містить, отримала onResume. Однак через особливості FragmentManager та ViewPager момент виклику onResume для Fragment може бути відстроченим відносно Activity. Наприклад, Fragment у ViewPager з offscreenPageLimit = 1 отримує onResume лише коли стає поточною сторінкою, а не при старті Activity.

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

onResume vs onStart: коли що використовувати

Розробники часто плутають onStart та onResume, розміщуючи код у непідходящому методі. Головне правило: onStart — для ресурсів, що працюють при видимості; onResume — для ресурсів, що потребують фокусу введення. Розглянемо конкретні сценарії та правильний вибір методу.

ОпераціяМетодОбґрунтування
Підписка на геолокаціюonStart / onStopGPS може працювати при частковій видимості
Відкриття камериonResume / onPauseКамера — монопольний ексклюзивний ресурс
BroadcastReceiveronStart / 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 використовується для запису аудіо та відео. Запит дозволів та підготовка MediaRecorder виконується в onCreate, а старт запису — в onResume. Якщо користувач перемикається на інший застосунок, onPause призупиняє запис, а onResume відновлює. Це стандартна поведінка для диктофонів та застосунків відеозапису.

kotlin
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 та onResume

Біометрична аутентифікація (BiometricPrompt) має викликатися лише коли Activity знаходиться в onResume. Якщо викликати її в onCreate або onStart, діалог біометрії може з’явитися до того, як Activity завершить ініціалізацію, що призведе до некоректної обробки результату. Виклик в onResume гарантує, що вікно біометрії буде показано в правильному контексті.

Паттерни та рекомендації

Розглянемо три перевірені паттерни роботи з onResume, які застосовуються в комерційних проєктах: скидання таймера неактивності, оновлення видимих даних та інтеграція з Jetpack Navigation.

Скидання таймера неактивності

У застосунках з конфіденційними даними (банкінг, медичні картки) onResume використовують для скидання таймера автоматичного виходу. Якщо користувач активно взаємодіє із застосунком, onResume викликається при кожному переході між екранами, і таймер скидається. Якщо користувач згорнув застосунок, onPause зупиняє таймер, а onResume при поверненні або скидає його, або запитує повторну аутентифікацію.

Оновлення даних при поверненні

Список, який має відображати актуальні дані при кожному поверненні на екран, оновлюють в onResume. Наприклад, якщо користувач створив новий запис в іншій Activity і повернувся назад, onResume перезавантажує список з локальної бази даних або з кешу ViewModel. Це забезпечує консистентність даних без ручного виклику notifyDataSetChanged.

kotlin
override fun onResume() {
    super.onResume()
    // ActivityResultLauncher повернув результат — оновлюємо список
    viewModel.refreshList()
    // Скидання таймера неактивності
    inactivityTimer.reset()
}

Jetpack Navigation та onResume

У Jetpack Navigation onResume фрагмента викликається при кожному поверненні до нього через зворотну навігацію. Цю властивість використовують для скидання стану UI: сховати клавіатуру, очистити поля пошуку, оновити заголовок тулбара. OnBackPressedCallback у зв’язці з onResume дає повний контроль над навігацією без дублювання коду.

Часті запитання

У чому різниця між onResume та onStart простими словами?

onStart — екран видимий. onResume — екран активний і готовий до взаємодії. Уявіть: ви дивитеся телевізор (onStart), але берете пульт у руки (onResume). Телевізор видимий завжди, але взаємодія починається лише з пультом. Якщо хтось закриває телевізор шторкою — екран перестає бути видимим (onStop). Якщо у вас забирають пульт — взаємодія припиняється (onPause), але телевізор все ще видимий.

Як часто викликається onResume?

onResume викликається кожного разу, коли Activity отримує фокус введення. Мінімальна кількість — один раз (при запуску). Максимальна залежить від сценаріїв використання: перемикання між екранами, відкриття діалогів, швидке блокування та розблокування пристрою — кожен такий сценарій викликає onResume при поверненні на екран.

Чому onResume — найкраще місце для відкриття камери?

Камера — ексклюзивний ресурс, доступний лише одному застосунку в момент часу. Якщо відкрити камеру в onCreate або onStart, вона залишиться заблокованою для інших застосунків навіть коли ваш застосунок неактивний. onResume гарантує, що камера відкрита лише коли Activity на передньому плані, а onPause негайно її закриває. Це стандарт Android-розробки, закріплений у документації CameraX та Camera2 API.

Чи може onResume не викликатися після onStart?

Так, onResume може не настати, якщо Activity перекривається іншою Activity одразу після появи. Наприклад, Activity A запускає Activity B у методі onCreate або onStart. У цьому випадку A отримує onStart → onPause → onStop, минаючи onResume. Система не викликає onResume, тому що Activity A ніколи не отримувала фокус введення.

Що не можна робити в onResume?

В onResume не можна виконувати тривалі синхронні операції: завантаження великих даних з мережі, складні SQL-запити, обробка зображень. Метод onResume працює в UI-потоці, і будь-яке блокування довше 100–200 мс призводить до затримки відгуку інтерфейсу. Всі важкі операції мають бути асинхронними — через корутини, RxJava або WorkManager. Також не рекомендується викликати finish() в onResume без перевірки — це може призвести до нескінченного циклу перестворення.

Підсумки

  • onResume — стан переднього плану з фокусом введення; Activity готове до взаємодії з користувачем
  • Ексклюзивні ресурси — камера, мікрофон, відеозахоплення відкривають в onResume та закривають в onPause
  • onResume vs onStart — onStart для видимих, onResume для активних ресурсів; діалог перериває onResume, але не onStart
  • Швидкодія — onResume має бути легким; всі важкі операції асинхронні
  • Fragment.onResume — залежить від видимості в ViewPager; перевіряти userVisibleHint або використовувати setMaxLifecycle
  • Типові завдання — скидання таймера, оновлення даних при поверненні, керування BiometricPrompt
  • Пара onResume/onPause — ресурси з монопольним доступом керуються виключно цією парою

Ми розробимо мобільний застосунок під ключ

IT Sectr створює застосунки для iOS та Android для стартапів і бізнесу з 2017 року. Ми проконсультуємо вас і запропонуємо найкраще рішення.

Обговорити проект

Читайте також