« Itinéraire perdu » : pourquoi Android Navigation Component devient fou
\n\nAvez-vous déjà lancé votre application Android, navigué vers un écran, appuyé sur « Retour » — et soudain l’application plantait avec l’erreur IllegalArgumentException : navigation destination xxx is unknown to this NavController ? Si oui, vous n’êtes pas seul. Cette question a recueilli des milliers de vues sur Stack Overflow, et un développeur sur deux qui commence à travailler avec Jetpack Navigation y est confronté.
Dans cet article, nous allons voir pourquoi l’IllegalArgumentException navigation destination unknown se produit, comment la diagnostiquer et, surtout, comment la corriger. Il y aura beaucoup de code vivant en Kotlin, des conseils pratiques et aucun « blabla ». C’est parti !
\n\nQu’est-ce que NavController et pourquoi « ne connaît-il pas » votre destination ?
\n\nPour commencer — un peu de théorie. NavController est le chef d’orchestre principal de la navigation sous Android. Il gère les transitions entre les écrans (fragments ou composables) sur la base du graphe de navigation — un fichier XML décrivant tous les itinéraires possibles. Lorsque vous appelez navController.navigate(R.id.some_destination), NavController recherche cet ID dans son graphe. S’il ne le trouve pas, il lance une IllegalArgumentException.
Cela semble logique, mais pourquoi cela se produit-il à l’exécution et non à la compilation ? Parce que le graphe de navigation est chargé dynamiquement, et l’erreur est souvent liée au fait que le graphe actuel (celui que contient NavController) n’inclut tout simplement pas la destination demandée.
\n\nLes scénarios d’erreur les plus fréquents
\n- \n
- Tentative de navigation vers un écran non décrit dans le graphe actuel — par exemple, vous changez de fragments alors que NavController provient du précédent. \n
- Utilisation de liens profonds (DeepLink) sans enregistrement correct — l’application est lancée via un lien, mais le graphe n’est pas encore chargé. \n
- Nettoyage de la pile arrière et tentative de navigation après cela — NavController « oublie » ses itinéraires. \n
- ID de destination incorrect — faute de frappe ou incohérence entre le nom dans le code et le XML. \n
Analyse sur un exemple réel (Kotlin)
\n\nImaginez que vous avez une application avec deux écrans : HomeFragment et ProfileFragment. Le graphe de navigation nav_graph.xml ressemble à ceci :
<!-- nav_graph.xml -->\n<navigation xmlns:android="http://schemas.android.com/apk/res/android"\n xmlns:app="http://schemas.android.com/apk/res-auto"\n android:id="@+id/nav_graph"\n app:startDestination="@id/homeFragment">\n\n <fragment\n android:id="@+id/homeFragment"\n android:name="com.example.app.HomeFragment"\n android:label="Home">\n <action\n android:id="@+id/action_home_to_profile"\n app:destination="@id/profileFragment" />\n </fragment>\n\n <fragment\n android:id="@+id/profileFragment"\n android:name="com.example.app.ProfileFragment"\n android:label="Profile" />\n</navigation>\n\nDans HomeFragment, vous effectuez la transition :
// HomeFragment.kt\nval navController = findNavController()\nnavController.navigate(R.id.action_home_to_profile)\n\nTout fonctionne. Mais que se passe-t-il si vous essayez d’appeler navController.navigate(R.id.profileFragment) depuis un autre contexte — par exemple, depuis Activity ou BroadcastReceiver ? Ou si vous rechargez le graphe ? C’est là qu’apparaît l’IllegalArgumentException : navigation destination xxx is unknown to this NavController.
Reproduire l’erreur
\n\nSupposons que vous ayez ajouté un bouton « Retour » dans la barre d’outils et écrit ce code :
\n\n// MainActivity.kt\nsupportActionBar?.setDisplayHomeAsUpEnabled(true)\n\noverride fun onOptionsItemSelected(item: MenuItem): Boolean