Cas d’usage : Comment gérer le système backpress d’une Activity Android ?

Julien Bouffard
L’Actualité Tech — Blog CBTW
4 min readMar 18, 2021

Comment Android gère le système backpress ?

Que se passe-t-il quand l’utilisateur clique sur le bouton ‘retour système’ sur son téléphone ?
Si notre activity hérite de AppCompatActivity, voici la hiérarchie d’héritage de votre activity jusqu’à Activity qui est la 1ère classe à gérer le backpress :

AppCompatActivity -> FragmentActivity -> androidx.activity.ComponentActivity -> androidx.core.app.ComponentActivity -> Activity

Le comportement par défaut de Activity

Android gère ce comportement grâce à un callback quand l’utilisateur relâche une touche et que le code de cette touche est le bouton back du téléphone.

Pour les versions supérieures à Android Eclair, le callback est mappé sur OnkeyUp qui va faire appel à une méthode onBackPressed définie dans la classe Activity.

L’implémentation par défaut va s’occuper dans l’ordre de soit fermer l’action bar, soit de pop le fragment en cours, soit de tuer l’activity en cours et de fermer l’app si celle-ci était l’activity root.

Activity.kt

La surcharge de androidx.activity.ComponentActivity

Plus tard dans la hiérarchie, androidx.activity.ComponentActivity va surcharger la méthode onBackPressed de Activity avec sa propre implémentation.

C’est donc cette implémentation qui sera exécutée lorsque l’utilisateur utilise la touche système de retour.

androidx.activity.ComponentActivity

Android introduit une nouvelle façon de gérer le backpress.

Utiliser un dispatcher (OnBackPressedDispatcher) qui va enregistrer des callbacks (OnBackPressedCallback) pour gérer le onBackPressed en découplant ce comportement de notre activity. Par composition, ces callbacks sont déclarés par les composants qui disposent de la logique métier.

Voyons comment gérer ce dispatcher pour exécuter ces callbacks.

OnBackPressedDispatcher.kt

Le dispatcher va itérer sur tous les callbacks enregistrés et exécuter la méthode handleOnBackPressed du dernier callback ajouté ayant un statut activé.

Le FragmentManager utilise d’ailleurs ce dispatcher pour pop les fragments quand l’utilisateur appuie sur la touche back. Quand un fragment s’attache à une activity, celui-ci enregistre un callback par défaut désactivé (le paramètre du constructeur du callback OnBackPressedCallback est isEnabled et gère l’activation par défaut du callback).

L’appel à execPendingActions dans handleOnBackPressed va réactiver le callback une fois toutes les pendingActions exécutées.

Le fragmentManager appelle finalement popBackStackImmediate.

Créer un comportement métier sur onBackPressed

Il arrive que les besoins métiers nécessitent de surcharger ce comportement.

On pourrait imaginer surcharger directement la méthode onBackPressed dans notre activity pour implémenter notre logique métier.

Pour autant, avec plusieurs fragments attachés à notre activity, la méthode pourrait devenir difficile à maintenir et gérer une responsabilité qui n’est pas la sienne.

Il est plus judicieux d’utiliser le OnBackPressedDispatcher qui va permettre de contrôler le comportement de façon précise sans toucher à notre activity.

Voici un mini-projet sur github pour illustrer le backpress avec le dispatcher.

Le concept : un fragment affiche un champ EditText. Quand l’utilisateur appuie sur le bouton back, le texte est enregistré automatiquement pour sauvegarder la saisie et éviter les pertes de données. Puis le fragment est popped pour venir à un autre fragment qui va lister l’historique des saisies.

L’enregistrement des saisies se fait sur le DataStore Android sur ce projet mais est totalement adaptable à une base de données Room ou un call api par exemple.

WriteStuffFragment.kt

Le fragment définit un unique champ texte et y attache un textWatcher.

Les callbacks sont définis au plus près de la fonctionnalité, dans le fragment ou le viewmodel par exemple plutôt que de déporter cette logique dans l’activity.

Un callback (saveCallback) pour enregistrer la saisie dans le repository, afficher un toast et pop le fragment pour revenir sur le fragment de liste d’historique des saisies.

Un autre callback (invalidCallback) pour afficher un message d’erreur quand le texte est vide et qui bloque l’utilisateur sur l’écran.

Le bon callback est dispatché dans le textWatcher en fonction de l’état du champ texte. J’ai pris le parti de supprimer les callbacks du dispatcher à chaque changement de saisie pour éviter de passer de nombreux callbacks qui ne seraient au final pas utilisés car seul le dernier ajouté et actif est exécuté.

C’est un exemple mais qui montre que le comportement associé au bouton back peut-être contrôlé très finement de manière découplée du framework Android.

Il est donc conseillé d’utiliser OnBackPressedDispatcher pour personnaliser le backpress système Android.

Pour aller plus loin

Si vous avez trouvé cet article intéressant, je vous invite à découvrir d’autres articles sur des POC que j’ai expérimenté avec ARCore et la réalité augmentée :

Et aussi :

Nous publions régulièrement des articles sur des sujets de développement produit web et mobile, data et analytics, sécurité, cloud, hyperautomatisation et digital workplace.
Suivez-nous pour être notifié des prochains articles et réaliser votre veille professionnelle.

Retrouvez aussi nos publications et notre actualité via notre newsletter, ainsi que nos différents réseaux sociaux : LinkedIn, Twitter, Youtube, Twitch et Instagram

Vous souhaitez en savoir plus ? Consultez notre site web et nos offres d’emploi.

--

--