Navigation
Bonnes pratiques de routage et navigation pour les applications Flutter utilisant GoRouter, le package de routage recommandé par l'équipe Flutter basé sur l'API Navigator 2.0.
Core Standards
Appliquez ces standards à TOUS les travaux de navigation :
- Utilisez
package:go_routerpour toute navigation — jamais le Navigator 2.0 brut ou les push/pop du Navigator 1.0 - Utilisez les annotations
@TypedGoRoutepour des routes type-safe — jamais les chemins bruts en chaîne de caractères dans les définitions de routes - Préférez
go()àpush()— utilisezpush()seulement si vous attendez des données de retour de la destination - N'utilisez jamais le paramètre
extra— cela casse le deep linking et ne fonctionne pas sur le web - Routes hiérarchiques imbriquées pour une navigation arrière correcte — structurez les routes comme des arbres parent-enfant, pas des listes plates
- Tirets pour la séparation de mots dans les URL — jamais de traits de soulignement ou camelCase dans les chemins URL
- Naviguez par nom de route, pas par chaînes de chemin brutes — utilisez la navigation par nom de route pour découpler les changements de chemin
- Utilisez les extensions
BuildContextpour la navigation — préférezcontext.goNamed()àGoRouter.of(context).goNamed()
Route Organization
Structurez les routes de manière hiérarchique avec des relations logiques parent-enfant. Les sous-routes garantissent que le bouton retour de la barre d'application s'affiche correctement et que les URLs restent propres.
Hierarchical Structure (Preferred)
/flutter
/flutter/news
/flutter/chat
/flutter/articles
/flutter/articles?category=all
/flutter/article/:id
/android
/android/news
/android/chat
Flat Structure (Avoid)
/flutter-news
/flutter-chat
/android-news
/android-chat
Les sous-routes hiérarchiques produisent une navigation arrière correcte automatiquement — quand un utilisateur est sur /flutter/news, le bouton retour navigue vers /flutter.
Type-Safe Routes
Utilisez les annotations @TypedGoRoute avec les classes GoRouteData pour éliminer les fautes de frappe et les conversions de paramètres manuelles. Le package go_router_builder génère des assistants de route type-safe à la compilation.
Basic Route
@TypedGoRoute<CategoriesPageRoute>(
name: 'categories',
path: '/categories',
)
@immutable
class CategoriesPageRoute extends GoRouteData {
const CategoriesPageRoute({
this.size,
this.color,
});
final String? size;
final String? color;
@override
Widget build(BuildContext context, GoRouterState state) {
return CategoriesPage(size: size, color: color);
}
}
Route with Sub-Routes
@TypedGoRoute<FlutterPageRoute>(
name: 'flutter',
path: '/flutter',
routes: [
TypedGoRoute<FlutterNewsPageRoute>(
name: 'flutterNews',
path: 'news',
),
TypedGoRoute<FlutterArticlesPageRoute>(
name: 'flutterArticles',
path: 'articles',
routes: [
TypedGoRoute<FlutterArticlePageRoute>(
name: 'flutterArticle',
path: 'article/:id',
),
],
),
],
)
@immutable
class FlutterPageRoute extends GoRouteData {
const FlutterPageRoute();
@override
Widget build(BuildContext context, GoRouterState state) {
return const FlutterPage();
}
}
Navigation Methods
go() vs push()
| Method | URL Updates | Back Button | Use Case |
|---|---|---|---|
go() |
Yes | App bar | Standard navigation between screens |
push() |
No | System | When expecting return data from popped route |
Using go() (Default)
const CategoriesPageRoute(size: 'small', color: 'blue').go(context);
L'utilisation de go() garantit que le bouton retour dans l'AppBar de l'application s'affiche quand la route actuelle a un parent vers lequel naviguer.
Using push() (Return Data Only)
final result = await DialogPageRoute().push<String>(context);
Utilisez push() seulement quand une route doit retourner des données (par exemple, une dialog collectant l'entrée utilisateur). Sur le web, push() ne met pas à jour la barre d'adresse.
BuildContext Extensions
Utilisez toujours les méthodes d'extension pour une syntaxe plus propre :
// Preferred
context.goNamed('flutterNews');
// Avoid
GoRouter.of(context).goNamed('flutterNews');
Parameter Strategies
Utilisez les paramètres de chemin (:id) pour l'identification de ressource et les paramètres de requête (?category=all) pour le filtrage optionnel. N'utilisez jamais extra — cela casse le deep linking et ne fonctionne pas sur le web.
Voir references/parameters.md pour des exemples complets de paramètres de chemin, paramètres de requête, et pourquoi extra est interdit.
Redirects
Les redirects peuvent être appliqués au niveau du routeur racine (par exemple, les garde d'authentification) et au niveau des routes individuelles (par exemple, les garde d'autorisation). Les redirects parents s'exécutent avant les redirects enfants.
Voir references/redirects.md pour des exemples de redirects au niveau racine et au niveau des routes.
Testing
Simulez GoRouter avec package:mocktail et enveloppez les widgets dans InheritedGoRouter pour les tests de widgets. Testez les redirects en construisant un GoRouter avec la logique de redirect cible et en affirmant la page résultante.
Voir references/testing.md pour des exemples de simulation de GoRouter et de test de redirects.
Common Patterns
Adding a New Route
- Créez le widget page (en suivant le pattern Page/View si vous utilisez Bloc)
- Définissez une classe
GoRouteDataavec l'annotation@TypedGoRoute - Ajoutez-la comme sous-route sous la route parent appropriée
- Exécutez
dart run build_runner build --delete-conflicting-outputspour régénérer les assistants de route - Naviguez en utilisant la classe de route type-safe générée
Deep Linking Setup
- Structurez les routes de manière hiérarchique avec des chemins URL significatifs
- Utilisez les paramètres de chemin pour l'identification de ressource
- Utilisez les paramètres de requête pour le filtrage — jamais
extra - Naviguez par nom de route afin que la restructuration de chemin ne casse pas les liens
- Testez les deep links en lançant l'application avec l'URL cible
Nested Navigation (Shell Routes)
@TypedShellRoute<AppShellRoute>(
routes: [
TypedGoRoute<HomePageRoute>(
name: 'home',
path: '/home',
),
TypedGoRoute<SettingsPageRoute>(
name: 'settings',
path: '/settings',
),
],
)
class AppShellRoute extends ShellRouteData {
@override
Widget builder(BuildContext context, GoRouterState state, Widget navigator) {
return AppShell(child: navigator);
}
}
Quick Reference
| Package | Purpose |
|---|---|
go_router |
Declarative routing built on Navigator 2.0 |
go_router_builder |
Code generation for type-safe route classes |
| Command | Purpose |
|---|---|
dart run build_runner build --delete-conflicting-outputs |
Generate type-safe route helpers |
dart run build_runner watch --delete-conflicting-outputs |
Watch and regenerate on changes |