Back Press Handling — is het mechanisme voor het onderscheppen en verwerken van de systeem „Terug” knop in Android, dat bepaalt welke actie wordt uitgevoerd wanneer erop wordt gedrukt. Volgens Android Developers (2024) is vanaf Android 11 de traditionele methode onBackPressed() vervangen door OnBackPressedDispatcher. De nieuwe API stelt componenten op elk niveau van de hiërarchie in staat om de druk te onderscheppen, niet alleen Activity. Belangrijkste verschil — ondersteuning voor meerdere callbacks in een keten met prioriteiten.
Belangrijkste punten
Back Press Handling — is het systeemmechanisme van Android dat bepaalt wat er gebeurt wanneer de gebruiker op de hardware- of software „Terug” knop drukt. Afhankelijk van de context kan het indrukken: het huidige scherm sluiten en terugkeren naar het vorige, het toetsenbord verbergen, de Drawer of Bottom Sheet sluiten, de app verlaten als de gebruiker zich op het hoofdscherm bevindt.
Het gedrag van de „Terug” knop is geëvolueerd met elke versie van Android. In Android 10 verschenen navigatiegebaren, in Android 11 — OnBackPressedDispatcher als standaard API, en in Android 13 — verbeterde ondersteuning voor predictive back gesture, waarbij het systeem een overgangsaninatie toont voordat de actie daadwerkelijk wordt uitgevoerd. Google beweegt consequent richting voorspelbaar en consistent Back Press-gedrag op alle apparaten.
Correcte verwerking van de „Terug” knop — een kritiek UX-element in een Android-app. De gebruiker verwacht dat het indrukken van „Terug” hem terugbrengt naar het vorige scherm in de navigatiestack, niet dat de app onverwacht wordt afgesloten. Schending van deze verwachting is een van de belangrijkste redenen voor negatieve beoordelingen en lage scores in Google Play.
De geschiedenis van de Back Press API in Android weerspiegelt de algemene evolutie van het platform: van een eenvoudige methode in Activity tot een flexibel callback-systeem met ondersteuning voor lifecycle en Compose. Laten we drie ontwikkelingsfasen bekijken.
Vanaf de allereerste Android API werd de „Terug” knop verwerkt in de methode onBackPressed van de klasse Activity. De ontwikkelaar overschreef deze methode en schreef zijn eigen logica. Het probleem was dat Fragment en View de druk niet konden onderscheppen — alle controle verliep via de Activity. Dit leidde tot opgeblazen Activity's en een complexe if-else-keten om te bepalen wie de druk moest verwerken.
Met Activity 1.0.0 (AndroidX) introduceerde Google OnBackPressedDispatcher. Dit is een centrale dispatcher die callbacks ontvangt van elke component — Activity, Fragment, Dialog, aangepaste View. Callbacks worden geregistreerd met opgave van volgorde (via priority) en kunnen dynamisch worden toegevoegd of verwijderd. OnBackPressedDispatcher wordt eerder aangeroepen dan de oude onBackPressed, waardoor de druk kan worden onderschept voordat de Activity deze verwerkt.
Android 13 introduceerde predictive back gesture — een systeemanimatie die laat zien waar het indrukken van „Terug” toe leidt, nog voordat de gebruiker het gebaar voltooit. Om deze animatie te ondersteunen, moeten ontwikkelaars OnBackPressedDispatcher gebruiken en aangeven of de callback de systeemanimatie ondersteunt via de eigenschap isEnabled. Als de callback predictive animation niet ondersteunt, toont het systeem een standaardanimatie die mogelijk niet overeenkomt met de context van de app.
| API | Minimale SDK | Fragment ondersteuning | Predictive Back |
|---|---|---|---|
| onBackPressed | API Level 1 | Via Activity | Nee |
| OnBackPressedDispatcher | Activity 1.0.0 | Direct | Gedeeltelijk |
| OnBackPressedDispatcher + lifecycle | Activity 1.3.0 | Lifecycle-aware | Volledig |
OnBackPressedDispatcher — is de kern van de nieuwe Back Press API. Het beheert de callback-keten en roept ze in volgorde aan tot de eerste die de gebeurtenis verwerkt. Als geen enkele callback de druk verwerkt, voert de dispatcher de standaardactie uit — het aanroepen van finish() voor Activity of popBackStack() voor Navigation Component.
Callback wordt geregistreerd via addCallback met opgave van LifecycleOwner en een OnBackPressedCallback-object. De callback bevat de eigenschap isEnabled — als deze op false staat, wordt de callback overgeslagen. Voor priority kan een waarde van 0 (laagste) tot Integer.MAX_VALUE worden doorgegeven. Fragment Activity Result API gebruikt dit mechanisme voor automatische registratie van callbacks die aan de levenscyclus zijn gekoppeld.
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)
}
Callback wordt automatisch verwijderd wanneer LifecycleOwner overgaat naar de status DESTROYED. Dit lost het oude probleem van callback-lekken bij schermrotatie op. Als een callback aan een Fragment is toegevoegd, is gegarandeerd dat deze wordt verwijderd bij vernietiging van het Fragment. Voor tijdelijke uitschakeling van de callback wordt de eigenschap isEnabled gebruikt — deze kan worden geschakeld zonder verwijdering en herregistratie.
De aanroepvolgorde is omgekeerd aan de toevoegingsvolgorde: de laatst toegevoegde callback krijgt als eerste de controle. Dit is logisch omdat het meest geneste UI-element (bijvoorbeeld Bottom Sheet binnen een Fragment) de druk eerder moet verwerken dan het bovenliggende Fragment. Als de diepste callback de druk niet verwerkt (isEnabled = false), wordt de controle doorgegeven aan de volgende in de keten.
Fragment API biedt eigen integratie met OnBackPressedDispatcher via de methode requireActivity().onBackPressedDispatcher. Vanaf Fragment 1.2.0 kan elk Fragment zijn eigen callback registreren die automatisch wordt gekoppeld aan de levenscyclus van het Fragment en wordt verwijderd bij vernietiging.
Registratie van callback in Fragment gebeurt in onCreate, onViewCreated of zelfs in de View zelf — belangrijk is alleen dat LifecycleOwner (Fragment) actief is. Wanneer Fragment overgaat naar de status STARTED, wordt de callback ingeschakeld, bij STOPPED — uitgeschakeld. Dit garandeert dat een verborgen Fragment (in ViewPager) de „Terug” druk niet zal verwerken.
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)
}
}
Dialoogvensters en BottomSheet onderscheppen automatisch de „Terug” druk om te sluiten. Als u een extra actie moet uitvoeren voordat u sluit — registreer dan een callback met een hogere prioriteit. Belangrijk: als u setCancelable(false) op Dialog hebt ingesteld, werkt de callback niet — dit is systeemgedrag.
Jetpack Compose biedt een declaratieve API voor het verwerken van de „Terug” knop via de composable-functie BackHandler. BackHandler accepteert enabled (een booleaanse waarde) en onBack — een callback die wordt aangeroepen bij indrukken. Als enabled = false, wordt de druk verder doorgegeven in de keten.
BackHandler registreert automatisch OnBackPressedCallback in de OnBackPressedDispatcher van de bovenliggende Activity. Het houdt rekening met de levenscyclus van composable: bij verlaten van de compositie wordt de callback verwijderd. enabled kan aan een status worden gekoppeld — bijvoorbeeld alleen een bevestigingsdialoog tonen als er niet-opgeslagen wijzigingen in het formulier zijn.
@Composable
fun EditScreen(hasUnsavedChanges: Boolean) {
BackHandler(enabled = hasUnsavedChanges) {
// Bevestigingsdialoog tonen
}
Column {
TextField(value = ..., onValueChange = ...)
}
}
Predictive back gesture in Compose wordt ondersteund vanaf Compose 1.5.0. BackHandler verwerkt automatisch de systeemovergangsaninatie als deze op het apparaat is ingeschakeld. Gebruik voor aangepaste predictive-animatie de modifier predictiveBackHandler, die de voortgang van het gebaar van 0 tot 1 retourneert.
Back Press Handling lijkt eenvoudig, maar in de praktijk maken ontwikkelaars een reeks systematische fouten. Laten we de meest voorkomende problemen en hun oplossingen bekijken op basis van Google's aanbevelingen en ervaring van de community.
Directe aanroep van finish() in handleOnBackPressed kan leiden tot onverwacht verlaten van de app als er achtergrondschermen in de navigatiestack zijn. Controleer altijd NavController.backStack via Navigation Component of Coordinator voordat u Activity sluit.
Als u een callback zonder LifecycleOwner registreert (met behulp van de oude addCallback zonder parameter), zal de callback eeuwig leven en kan NullPointerException veroorzaken als de Activity al is vernietigd. Gebruik altijd addCallback(this, callback) met LifecycleOwner.
Stel voor modale vensters (Bottom Sheet, Dialog) altijd isEnabled = true alleen in wanneer het venster zichtbaar is. Gebruik addCallback met een lambda die de toestand van het venster controleert. Navigation Component beheert dit automatisch voor NavHost.
Snelle dubbele druk op „Terug” kan leiden tot dubbele aanroep van finish(). Gebruik een vlag of throttleLast ter bescherming tegen herhaalde aanroepen binnen 500 ms. Navigation Component verwerkt deze situatie ingebouwd, maar in aangepaste scenario's moet u de bescherming handmatig implementeren.
private var lastBackPressTime = 0L
override fun handleOnBackPressed() {
val currentTime = System.currentTimeMillis()
if (currentTime - lastBackPressTime > 500) {
lastBackPressTime = currentTime
navigateBack()
}
}
Veelgestelde vragen
onBackPressed is verouderd (deprecated) in Android 11 omdat het alleen op Activity-niveau werkt. OnBackPressedDispatcher stelt elke component (Fragment, Dialog, View) in staat om de druk te onderscheppen via een uniform mechanisme met ondersteuning voor de levenscyclus.
Het Android-systeem converteert een swipe-gebaar van de rand naar een systeem „Terug” druk voordat de app deze ontvangt. Op het niveau van OnBackPressedDispatcher kunt u deze twee gebeurtenissen niet onderscheiden — beide komen binnen als handleOnBackPressed.
Ja, de verwerking van OnBackPressedDispatcher is hetzelfde voor apparaten met drie knoppen en met gebarennavigatie. De onderscheppingscode is niet afhankelijk van het navigatietype — het systeem converteert zelf het gebaar naar een aanroep van de dispatcher.
Schakel predictive back in de Developer Options van de Android 13+ emulator in. Gebruik ADB: `adb shell settings put global enable_back_animation 1`. Na inschakeling toont de systeemanimatie een voorbeeld van de overgang bij het indrukken van „Terug”.
Controleer twee voorwaarden: LifecycleOwner moet in de status STARTED of RESUMED zijn en isEnabled van de callback moet true zijn. Als aan beide voorwaarden is voldaan, zorg er dan voor dat de callback aan de juiste OnBackPressedDispatcher is toegevoegd — gebruik requireActivity().onBackPressedDispatcher in Fragment.
Samenvatting
We ontwikkelen een mobiele applicatie turnkey
IT Sectr creëert sinds 2017 iOS- en Android-applicaties voor startups en bedrijven. We adviseren u en stellen de beste oplossing voor.
Lees ook