Back Press Handling у Android-у: суштина, механизми и имплементација

Аутор: IT Sectr Објављено: 2026-06-10 Време читања: 9 мин

Back Press Handling — је механизам пресретања и обраде системског дугмета „Назад” у Android-у, који одређује која се радња извршава при његовом притиску. Према Android Developers (2024), од Android 11 традиционални метод onBackPressed() замењен је са OnBackPressedDispatcher. Нови API омогућава компонентама на било ком нивоу хијерархије да пресретну притисак, а не само Activity. Кључна разлика — подршка за вишеструке callback-ове у ланцу са приоритетима.

Главно

  • Back Press Handling — механизам обраде системског дугмета „Назад” у Android-у
  • OnBackPressedDispatcher — нови API који је заменио застарели onBackPressed()
  • Callback се региструју са приоритетом и извршавају се по реду ланца
  • Jetpack Compose користи BackHandler за пресретање притиска у composable-у
  • Support Library обезбеђује уназадну компатибилност до API Level 14

Шта је Back Press Handling

Back Press Handling — је системски механизам Android-а који одређује шта се дешава када корисник притисне хардверско или софтверско дугме „Назад”. У зависности од контекста, притисак може: затворити тренутни екран и вратити се на претходни, сакрити тастатуру, затворити Drawer или Bottom Sheet, изаћи из апликације ако се корисник налази на кореном екрану.

Понашање дугмета „Назад” еволуирало је са сваком верзијом Android-а. У Android 10 појавили су се гестови навигације, у Android 11 — OnBackPressedDispatcher као стандардни API, а у Android 13 — побољшана подршка за predictive back gesture, где систем приказује анимацију прелаза пре стварног извршења радње. Google се доследно креће ка предвидљивом и конзистентном понашању Back Press-а на свим уређајима.

Правилна обрада дугмета „Назад” — критични елемент UX у Android апликацији. Корисник очекује да га притисак „Назад” враћа на претходни екран у стеку навигације, а не да затвара апликацију изненада. Кршење овог очекивања је један од главних разлога негативних рецензија и ниских оцена у Google Play-ју.

Еволуција Back Press API-ја: од onBackPressed до OnBackPressedDispatcher

Историја Back Press API-ја у Android-у одражава општу еволуцију платформе: од једноставног метода у Activity-ју до флексибилног система callback-ова са подршком за lifecycle и Compose. Размотримо три фазе развоја.

Ера onBackPressed (API Level 1–30)

Од првог Android API-ја дугме „Назад” се обрађивало у методу onBackPressed класе Activity. Програмер је превазилазио овај метод и писао своју логику. Проблем је био у томе што Fragment и View нису могли да пресретну притисак — све управљање је ишло преко Activity-ја. То је доводило до надувених Activity-ја и сложеног ланца if-else за одређивање ко треба да обради притисак.

Појава OnBackPressedDispatcher-а (Activity 1.0.0)

Са Activity 1.0.0 (AndroidX) Google је представио OnBackPressedDispatcher. Ово је централни диспечер који прима callback-ове од било које компоненте — Activity, Fragment, Dialog, прилагођеног View-а. Callback-ови се региструју са одређивањем редоследа (путем priority) и могу се динамички додавати или уклањати. OnBackPressedDispatcher се позива раније од старог onBackPressed-а, што омогућава пресретање притиска пре него што га Activity обради.

Predictive Back Gesture (Android 13+)

Android 13 је увео predictive back gesture — системску анимацију која показује куда води притисак „Назад”, још пре него што корисник заврши гест. За подршку овој анимацији, програмери морају да користе OnBackPressedDispatcher и да назначе да ли callback подржава системску анимацију кроз својство isEnabled. Ако callback не подржава predictive animation, систем приказује подразумевану анимацију која можда не одговара контексту апликације.

APIМинимални SDKПодршка за FragmentPredictive Back
onBackPressedAPI Level 1Преко Activity-јаНе
OnBackPressedDispatcherActivity 1.0.0ДиректнаДелимична
OnBackPressedDispatcher + lifecycleActivity 1.3.0Lifecycle-awareПотпуна

OnBackPressedDispatcher — архитектура и ланац callback-ова

OnBackPressedDispatcher — је језгро новог Back Press API-ја. Он управља ланцем callback-ова, позивајући их по реду до првог који обради догађај. Ако ниједан callback не обради притисак, диспечер извршава подразумевану радњу — позив finish() за Activity или popBackStack() за Navigation Component.

Регистрација callback-а са приоритетом

Callback се региструје кроз addCallback са навођењем LifecycleOwner-а и објекта OnBackPressedCallback. Callback садржи својство isEnabled — ако је постављено на false, callback се прескаче. За priority се може проследити вредност од 0 (најнижи) до Integer.MAX_VALUE. Fragment Activity Result API користи овај механизам за аутоматску регистрацију callback-ова везаних за животни циклус.

kotlin
override fun onCreate(savedInstanceState: Bundle?) {
    super.onCreate(savedInstanceState)
    val callback = object : OnBackPressedCallback(enabled = true) {
        override fun handleOnBackPressed() {
            if (isDrawerOpen) { closeDrawer() }
            else { isEnabled = false; onBackPressed() }
        }
    }
    onBackPressedDispatcher.addCallback(this, callback)
}

Lifecycle-aware чишћење

Callback се аутоматски уклања када LifecycleOwner пређе у стање DESTROYED. Ово решава стари проблем цурења callback-а при ротацији екрана. Ако је callback додат у Fragment, гарантовано ће бити уклоњен при уништењу Fragment-а. За привремено искључивање callback-а користи се својство isEnabled — може се пребацивати без уклањања и поновне регистрације.

Ланац позивања

Редослед позивања је обрнут редоследу додавања: последњи додати callback добија контролу први. Ово је логично јер најдубље угнежђени UI елемент (нпр. Bottom Sheet унутар Fragment-а) треба да обради притисак раније него родитељски Fragment. Ако најдубљи callback не обрађује притисак (isEnabled = false), контрола се преноси следећем у ланцу.

Back Press у Fragment-у и дијалозима

Fragment API обезбеђује сопствену интеграцију са OnBackPressedDispatcher-ом кроз метод requireActivity().onBackPressedDispatcher. Почевши од Fragment 1.2.0, сваки Fragment може да региструје свој callback који се аутоматски везује за животни циклус Fragment-а и уклања се при његовом уништењу.

Callback у Fragment-у

Регистрација callback-а у Fragment-у се врши у onCreate, onViewCreated или чак у самом View-у — важно је само да LifecycleOwner (Fragment) буде активан. Када Fragment пређе у стање STARTED, callback се укључује, при STOPPED — искључује. Ово гарантује да скривени Fragment (у ViewPager-у) неће обрађивати притисак „Назад”.

kotlin
class EditorFragment : Fragment() {
    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        val callback = object : OnBackPressedCallback(true) {
            override fun handleOnBackPressed() {
                showDiscardDialog()
            }
        }
        requireActivity().onBackPressedDispatcher.addCallback(this, callback)
    }
}

Dialog и BottomSheetDialog

Дијалози и BottomSheet аутоматски пресрећу притисак „Назад” за затварање. Ако треба да извршите додатну радњу пре затварања — региструјте callback са вишим приоритетом. Важно: ако сте поставили setCancelable(false) на Dialog, callback неће радити — ово је системско понашање.

Back Press Handling у Jetpack Compose-у

Jetpack Compose обезбеђује декларативни API за обраду дугмета „Назад” кроз composable функцију BackHandler. BackHandler прима enabled (булову вредност) и onBack — callback који се позива при притиску. Ако је enabled = false, притисак се прослеђује даље у ланцу.

BackHandler у Compose-у

BackHandler аутоматски региструје OnBackPressedCallback у OnBackPressedDispatcher-у родитељског Activity-ја. Он узима у обзир животни циклус composable-а: при изласку из композиције callback се уклања. enabled може бити везан за стање — на пример, приказивати дијалог потврде само ако у форми постоје несачуване измене.

kotlin
@Composable
fun EditScreen(hasUnsavedChanges: Boolean) {
    BackHandler(enabled = hasUnsavedChanges) {
        // Прикажи дијалог потврде
    }

    Column {
        TextField(value = ..., onValueChange = ...)
    }
}

Predictive Back у Compose-у

Predictive back gesture у Compose-у је подржан почевши од Compose 1.5.0. BackHandler аутоматски обрађује системску анимацију прелаза ако је укључена на уређају. За прилагођену predictive анимацију користите модификатор predictiveBackHandler, који враћа напредак геста од 0 до 1.

Типичне грешке и best practices

Back Press Handling делује једноставно, али у пракси програмери праве низ систематских грешака. Размотримо најчешће проблеме и начине њиховог решавања на основу препорука Google-а и искуства заједнице.

Грешка: позив finish() без провере стека навигације

Директан позив finish() у handleOnBackPressed може довести до неочекиваног изласка из апликације ако у стек навигације постоје позадински екрани. Увек проверавајте NavController.backStack кроз Navigation Component или Coordinator пре затварања Activity-ја.

Грешка: игнорисање lifecycle-а при регистрацији callback-а

Ако региструјете callback без LifecycleOwner-а (користећи стари addCallback без параметра), callback ће живети вечно и може изазвати NullPointerException ако је Activity већ уништено. Увек користите addCallback(this, callback) са LifecycleOwner-ом.

Best Practice: прекидање ланца за модалне прозоре

За модалне прозоре (Bottom Sheet, Dialog) увек постављајте isEnabled = true само када је прозор видљив. Користите addCallback са ламбдом која проверава стање прозора. Navigation Component аутоматски управља овим за NavHost.

Best Practice: обрада двоструког притиска

Брзи двоструки притисак „Назад” може довести до двоструког позива finish(). Користите флаг или throttleLast за заштиту од поновљених позива у року од 500 ms. Navigation Component уграђено обрађује ову ситуацију, али у прилагођеним сценаријима морате ручно имплементирати заштиту.

kotlin
private var lastBackPressTime = 0L

override fun handleOnBackPressed() {
    val currentTime = System.currentTimeMillis()
    if (currentTime - lastBackPressTime > 500) {
        lastBackPressTime = currentTime
        navigateBack()
    }
}

Често постављана питања

Зашто је onBackPressed постао deprecated?

onBackPressed је постао deprecated у Android 11 јер ради само на нивоу Activity-ја. OnBackPressedDispatcher омогућава било којој компоненти (Fragment, Dialog, View) да пресретне притисак кроз јединствени механизам са подршком за животни циклус.

Како разликовати притисак „Назад” од геста превлачења?

Android систем претвара гест превлачења са ивице у системски притисак „Назад” пре него што га апликација прими. На нивоу OnBackPressedDispatcher-а не можете разликовати ова два догађаја — оба долазе као handleOnBackPressed.

Да ли треба подржавати дугме „Назад” на уређајима са гестовима?

Да, обрада OnBackPressedDispatcher-а је иста за уређаје са три дугмета и са гест навигацијом. Код за пресретање не зависи од типа навигације — систем сам претвара гест у позив диспечера.

Како тестирати predictive back gesture на емулатору?

Укључите predictive back у Developer Options емулатора Android 13+. Користите ADB: `adb shell settings put global enable_back_animation 1`. Након укључивања, системска анимација ће приказати преглед прелаза при притиску „Назад”.

Шта радити ако се callback не позива?

Проверите два услова: LifecycleOwner мора бити у стању STARTED или RESUMED, а isEnabled callback-а мора бити true. Ако су оба услова испуњена, уверите се да је callback додат у прави OnBackPressedDispatcher — користите requireActivity().onBackPressedDispatcher у Fragment-у.

Резиме

  • Back Press Handling — механизам обраде системског дугмета „Назад” у Android-у
  • OnBackPressedDispatcher — савремени API који је заменио onBackPressed() од Android 11
  • Callback се региструју кроз addCallback са LifecycleOwner-ом и аутоматски се чисте
  • Ланац позивања — последњи додати callback са isEnabled=true први обрађује притисак
  • У Fragment-у callback се везује за животни циклус и искључује се при скривању фрагмента
  • Jetpack Compose користи BackHandler composable за декларативну обраду
  • Predictive back gesture — системска анимација прелаза, доступна од Android 13+

Развићемо мобилну апликацију под кључ

IT Sectr креира iOS и Android апликације за стартапе и предузећа од 2017. године. Саветоваћемо вас и предложити најбоље решење.

Разговарајте о пројекту

Прочитајте такође