Article original : How to Get Started With Navigation in Flutter Using AutoRoute
La navigation est l'une des parties les plus importantes de toute application mobile. Les utilisateurs s'attendent à passer de manière fluide entre des écrans tels que l'accueil, les paramètres, le profil, et plus encore.
Bien que Flutter fournisse une navigation intégrée via Navigator, la gestion des routes peut rapidement devenir complexe dans les grandes applications. C'est là que les packages de routage comme AutoRoute interviennent. AutoRoute simplifie la navigation en générant des routes fortement typées, en réduisant le code redondant (boilerplate) et en rendant votre base de code plus facile à maintenir.
Cet article vous guidera à travers la configuration et l'utilisation d'AutoRoute dans un projet Flutter. À la fin, vous disposerez d'un projet fonctionnel avec plusieurs écrans et un système de routage structuré.
Table des matières
Prérequis
Avant de commencer, vous devriez avoir :
Le SDK Flutter installé et configuré (Guide d'installation Flutter).
Une compréhension de base des widgets Flutter, des widgets stateless vs stateful, et de l'API
Navigator.Une familiarité avec l'exécution de commandes dans le terminal.
Un IDE comme Android Studio, VS Code ou IntelliJ.
Si vous savez déjà comment construire des applications Flutter simples, vous êtes prêt.
Ce que nous allons construire
Nous allons créer une application Flutter avec quatre écrans :
Control Screen : l'écran principal avec des boutons pour naviguer vers les autres écrans.
Screen 1, Screen 2, Screen 3 : des pages simples qui démontrent la navigation.
Notre navigation sera entièrement gérée par AutoRoute, assurant une structure de projet propre et évolutive.
Étape 1 : Configuration du projet
Commencez par créer un nouveau projet Flutter :
flutter create auto_route_example
Naviguez dans le dossier du projet et ouvrez le fichier pubspec.yaml. Ajoutez les dépendances suivantes :
dependencies:
auto_route: ^7.8.4
dev_dependencies:
auto_route_generator: 7.3.2
build_runner:
Exécutez la commande ci-dessous pour installer les packages :
flutter pub get
Étape 2 : Organisation de la structure du projet
Pour l'évolutivité, gardez votre projet organisé. Créez la structure de dossiers suivante à l'intérieur de lib :
/lib
/screens
/sub_screens
screen1.dart
screen2.dart
screen3.dart
control_screen.dart
/route_config
app_route.dart
main.dart
Cette structure sépare les écrans de la logique de routage, rendant l'application plus facile à maintenir.
Étape 3 : Définition des routes avec AutoRoute
Avant de commencer à annoter les écrans réels, configurons d'abord la configuration des routes. Ce fichier agira comme la carte de navigation de notre application : il indique à AutoRoute quels chemins existent et vers quels écrans ils doivent pointer.
Créez lib/route_config/app_route.dart et ajoutez ce qui suit :
import 'package:auto_route/annotations.dart';
import 'package:auto_route/auto_route.dart';
import 'app_route.gr.dart'; // fichier généré
@AutoRouterConfig()
class AppRouter extends $AppRouter {
@override
List<AutoRoute> get routes => [
AutoRoute(path: '/', page: Controlscreen.page),
AutoRoute(path: '/screen1', page: Screen1.page),
AutoRoute(path: '/screen2', page: Screen2.page),
AutoRoute(path: '/screen3', page: Screen3.page),
];
}
Analyse du code :
@AutoRouterConfig()dit à AutoRoute : « Voici la configuration centrale de routage. Veuillez l'utiliser pour générer le système de navigation. »class AppRouter extends $AppRouter:AppRouterest notre définition de routeur.$AppRoutersera généré par AutoRoute une fois que nous aurons exécuté la génération de code. Il contient le travail lourd (comme les classes de routes et les helpers).
List<AutoRoute> get routes => [...]
C'est ici que nous déclarons la carte de navigation de notre application.
Chaque
AutoRoutepossède un path (/screen1) et une page (Screen1.page).
Exemple :
/→Controlscreen(notre page de démarrage)./screen1→Screen1./screen2→Screen2./screen3→Screen3.
Pour l'instant, ces pages (Screen1.page, etc.) n'existent pas encore. Nous les créerons et les annoterons à l'Étape 6.
page: Screen1.pageCe getter
.pagene deviendra disponible qu'après avoir annoté les écrans avec@RoutePage.AutoRoute s'appuie sur cette annotation pour générer les usines (factories) de pages correctes.
Pourquoi faire cela avant les écrans ?
En définissant les routes tôt, vous établissez un plan de navigation clair pour votre application. Plus tard, lorsque nous créerons les écrans, nous les « brancherons » simplement sur cette structure avec @RoutePage. Cela aide à garder le tutoriel logique : définir d'abord la carte, puis construire les destinations.
Étape 4 : Génération des fichiers de route
Pour générer les fichiers de route, exécutez :
flutter pub run build_runner build
Ou, pour surveiller les changements automatiquement :
flutter pub run build_runner watch
Cela crée app_route.gr.dart dans le dossier route_config. Le fichier comprend des classes fortement typées pour chaque écran, telles que Controlscreen, Screen1, Screen2, et Screen3.
Cela signifie qu'au lieu de s'appuyer sur des chaînes de caractères brutes pour la navigation, vous utiliserez ces classes générées, réduisant ainsi les bugs liés aux fautes de frappe et offrant une meilleure autocomplétion dans l'IDE.
Étape 5 : Configuration d'AutoRoute dans main.dart
Dans main.dart, configurez l'application pour utiliser AutoRoute :
import 'package:flutter/material.dart';
import 'package:flutter/services.dart';
import 'route_config/app_route.dart';
void main() {
runApp(const MyApp());
}
class MyApp extends StatelessWidget {
const MyApp({super.key});
@override
Widget build(BuildContext context) {
final appRouter = AppRouter();
SystemChrome.setSystemUIOverlayStyle(
const SystemUiOverlayStyle(
statusBarColor: Colors.transparent,
statusBarIconBrightness: Brightness.dark,
),
);
return MaterialApp.router(
title: 'Flutter AutoRoute Example',
theme: ThemeData(
colorScheme: ColorScheme.fromSeed(seedColor: Colors.brown),
useMaterial3: true,
),
routerConfig: appRouter.config(),
);
}
}
Points clés dans ce code :
MaterialApp.routerremplace leMaterialApptraditionnel lors de l'utilisation d'AutoRoute.appRouter.config()fournit la configuration d'AutoRoute.
Étape 6 : Création des écrans
Dans Flutter, chaque page ou section de votre application est généralement représentée par un screen (écran). Les écrans ne sont que des widgets (généralement enveloppés dans un Scaffold) qui contiennent l'interface utilisateur et la logique de cette page. Puisque nous utilisons AutoRoute, chaque écran vers lequel nous voulons naviguer doit être annoté avec @RoutePage.
L'annotation @RoutePage dit à AutoRoute : « Ce widget est une route. Veuillez l'inclure dans le système de routes généré. »
Sans cette annotation, AutoRoute ne connaîtra pas l'écran, et vous ne pourrez pas y naviguer via le routeur.
screen1.dart
import 'package:auto_route/annotations.dart';
import 'package:flutter/material.dart';
@RoutePage(name: 'Screen1')
class Screen1 extends StatelessWidget {
const Screen1({super.key});
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(title: const Text('Screen 1')),
body: const Center(child: Text('Welcome to Screen 1')),
);
}
}
Analyse du code ici :
@RoutePage(name: 'Screen1')Cette annotation enregistre le widget en tant que page routable.
Le paramètre
namedonne à AutoRoute un identifiant clair pour l'écran, qui sera également reflété dans le fichierapp_route.gr.dartgénéré.
class Screen1 extends StatelessWidgetDéfinit l'écran comme un widget stateless car il n'a pas d'état dynamique dans cet exemple.
Pour des pages plus complexes (comme des formulaires ou des tableaux de bord), vous pourriez utiliser un
StatefulWidget.
ScaffoldFournit la structure de mise en page de base pour les applications Material Design.
Contient l'
AppBar(barre supérieure avec le titre) et lebody(zone de contenu principal).
AppBar(title: const Text('Screen 1'))- Affiche une barre d'application supérieure avec le titre "Screen 1".
body: Center(child: Text('Welcome to Screen 1'))Centre le texte au milieu de l'écran.
Dans les applications réelles, c'est ici que vous ajouteriez vos widgets (listes, formulaires, tableaux de bord, etc.).
Répéter pour les autres écrans
Suivez exactement la même structure pour Screen2 et Screen3 :
Créez
screen2.dartetscreen3.dartà l'intérieur desub_screens.Annotez chaque classe avec
@RoutePageet donnez-lui un nom unique (Screen2,Screen3).Mettez à jour l'interface utilisateur à l'intérieur du
bodypour refléter de quel écran il s'agit.
Par exemple :
@RoutePage(name: 'Screen2')
class Screen2 extends StatelessWidget {
const Screen2({super.key});
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(title: const Text('Screen 2')),
body: const Center(child: Text('Welcome to Screen 2')),
);
}
}
Pourquoi est-ce important ?
AutoRoute scanne votre projet et recherche les annotations @RoutePage. Il génère ensuite des classes de navigation fortement typées afin que vous puissiez écrire context.router.push(const Screen2()) au lieu de taper manuellement des chaînes de route comme '/screen2'. Cela élimine l'erreur humaine (comme les fautes de frappe dans les chaînes de route) et rend la navigation plus facile à maintenir à mesure que votre application grandit.
Étape 7 : Écran de contrôle
Le ControlScreen fait office de point d'entrée de notre application. C'est le premier écran qui se charge au démarrage de l'application (car dans app_route.dart, nous avons configuré / > Controlscreen).
Cet écran ne montre aucun contenu complexe, à la place, il fournit des boutons pour naviguer vers d'autres écrans. Pensez-y comme à un menu ou un tableau de bord qui vous dirige vers les autres routes.
import 'package:auto_route/annotations.dart';
import 'package:auto_route/auto_route.dart';
import 'package:flutter/material.dart';
enum Screen { screen1, screen2, screen3 }
@RoutePage(name: 'Controlscreen')
class ControlScreen extends StatelessWidget {
const ControlScreen({super.key});
void navigateToScreen(BuildContext context, Screen screen) {
switch (screen) {
case Screen.screen1:
context.router.pushNamed('/screen1');
break;
case Screen.screen2:
context.router.pushNamed('/screen2');
break;
case Screen.screen3:
context.router.pushNamed('/screen3');
break;
}
}
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(title: const Text('Control Screen')),
body: Center(
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: [
ElevatedButton(
onPressed: () => navigateToScreen(context, Screen.screen1),
child: const Text('Navigate to Screen 1'),
),
const SizedBox(height: 10),
ElevatedButton(
onPressed: () => navigateToScreen(context, Screen.screen2),
child: const Text('Navigate to Screen 2'),
),
const SizedBox(height: 10),
ElevatedButton(
onPressed: () => navigateToScreen(context, Screen.screen3),
child: const Text('Navigate to Screen 3'),
),
],
),
),
);
}
}
Analyse étape par étape du code :
@RoutePage(name: 'Controlscreen')Marque
ControlScreencomme une page routable.AutoRoute générera une entrée
Controlscreen.pagepour une utilisation dansapp_route.dart.
enum Screen { screen1, screen2, screen3 }Nous définissons une énumération pour nos écrans cibles.
Cela rend la méthode de navigation plus propre et moins sujette aux erreurs que de taper des chaînes brutes à plusieurs endroits.
navigateToScreen(BuildContext context, Screen screen)Une méthode helper qui vérifie quel écran nous voulons (basé sur l'enum) et appelle ensuite
context.router.pushNamed('/screenX').context.routerprovient d'AutoRoute, il vous donne accès à la pile de navigation de l'application.pushNamed('/screen1')correspond au chemin que nous avons défini plus tôt dansapp_route.dart:AutoRoute(path: '/screen1', page: Screen1.page),C'est ainsi que fonctionne la connexion bouton → chemin → route.
Mise en page UI (
Scaffold)AppBar(title: Text('Control Screen'))ajoute une barre de titre en haut.Columnavec 3 boutons : chaque bouton appellenavigateToScreen()avec une valeur d'enum différente.
Exemple :
Bouton 1
navigateToScreen(context, Screen.screen1): navigue vers/screen1.Bouton 2 : navigue vers
/screen2.Bouton 3 : navigue vers
/screen3.
Comment tout cela fonctionne ensemble
Démarrage de l'application : Le routeur charge
/, qui pointe versControlscreen.L'utilisateur appuie sur un bouton :
navigateToScreen()s'exécute et appellecontext.router.pushNamed('/screenX').AutoRoute fait correspondre le chemin : Il recherche
/screenXdans la liste des routes que nous avons définie dansapp_route.dart.Le code généré prend le relais :
app_route.gr.dart(généré par AutoRoute) crée et pousse le bon widget d'écran sur la pile.
Le résultat : la navigation fonctionne sans écrire manuellement le code redondant de Navigator.push. AutoRoute gère tout pour vous.
Captures d'écran




Bonnes pratiques lors de l'utilisation d'AutoRoute
Organisez toujours les routes dans un dossier dédié (
route_config) pour séparer les préoccupations.Utilisez des routes fortement typées (classes générées) au lieu de chaînes brutes. Par exemple, utilisez
Screen1()au lieu de'/screen1'.Tirez parti des routes imbriquées pour les applications complexes (ex: onglets, flux d'authentification).
Utilisez des gardes (guards) dans AutoRoute pour protéger les routes qui nécessitent une authentification.
Gardez les écrans indépendants, évitez de placer la logique de navigation à l'intérieur des widgets d'écran sauf si nécessaire.
Conclusion
AutoRoute simplifie la navigation dans les applications Flutter en générant du code répétitif, en assurant la sécurité des types et en offrant des fonctionnalités avancées comme la navigation imbriquée et les gardes. Avec une structure de projet propre et de bonnes pratiques, vous pouvez faire évoluer votre application Flutter en toute confiance.
Pour un apprentissage plus approfondi et des fonctionnalités avancées, reportez-vous à la documentation officielle :
AutoRoute sur pub.dev