Navigation Android en double – Bug ou fonctionnalité ?
J’ai récemment trouvé un bogue qui pouvait faire planter toutes les applications que j’ai créées. Dans certaines applications, le plantage ne s’était jamais produit, bien que le bogue soit présent, et dans d’autres, le plantage se produirait 1 sur 1 million de sessions ou plus, ce qui faisait du problème une faible priorité.
J’utilise toujours une carte de navigation où chaque fragment a une liste d’actions disponibles, quelque chose comme ceci :
Et, à titre d’exemple, HomeFragment a deux comptes sur lesquels vous pouvez cliquer et accéder à AccountFragment.
Maintenant, si vous cliquez sur account1 et account2 très rapidement (presque simultanément), l’application plante avec :
Exception fatale : java.lang.IllegalArgumentException
Action de navigation / destination no.shortcut : id / to_account introuvable dans la destination actuelle a (no.shortcut : id / account_fragment) classe = no.shortcut.AccountFragment
Cliquez sur l’écouteur pour les déclencheurs account1 et accédez à AccountFragment.
L’écouteur de clic pour account2 se déclenche et essaie de naviguer à nouveau vers Account, mais nous sommes déjà dans AccountFragment. AccountFragment n’a pas accès à l’action/cible AccountFragment, ce qui provoque le blocage de l’application.
Si vous cliquez sur deux « boutons » qui naviguent et que la deuxième action / direction de navigation n’est pas disponible pour la première destination, l’application plante avec IllegalArgumentException.
La « solution » la plus simple consiste à déclarer toutes les actions au niveau supérieur. Si chaque partition a accès à toutes les autres partitions, elle ne plantera pas. Cependant, il naviguera deux fois et mettra la première destination sur la pile, ce qui peut être déroutant si l’utilisateur ne réalise pas qu’il a double-cliqué.
👆 Pas de plantage car l’action est disponible pour tous les fragments.
Une meilleure solution consiste à envelopper la fonction de navigation et à valider que la destination actuelle est la même que la destination de l’appel. Nous pourrions le faire avec une simple instruction if avant chaque appel de navigation :
Cependant, je trouve qu’il est un peu difficile de transmettre l’identifiant de la cible actuelle à chaque fois, donc une meilleure solution pourrait être de comparer le nom de classe de l’appelant avec le nom de classe de la cible actuelle :
Avec cette solution, le premier appel de navigation sera exécuté et le second sera ignoré. Le travail de refactoring devient également plus facile car tout ce que nous avons à faire est de remplacerfindNavController.navigate()
avec notrenavigate()
Occupation.
Commentaires
Laisser un commentaire