Différences entre GoRouter et Navigator 2.0
Aujourd'hui, je vais démontrer comment naviguer entre les pages avec Flutter. Naviguer dans une application Flutter peut se faire de plusieurs manières. Voici les principales différences entre Navigator 2.0 (la solution native de Flutter) et GoRouter (une bibliothèque tierce qui simplifie la navigation) :
Navigator 2.0
-
Intégré à Flutter :
Il s'agit de la solution de navigation déclarative native, directement supportée par Flutter. -
Flexibilité et contrôle :
Offre une gestion granulaire de la pile de pages, permettant un contrôle précis sur les transitions, le deep linking et la gestion de l'historique. -
Complexité :
L'implémentation nécessite de travailler avec des concepts commeRouterDelegate
etRouteInformationParser
, ce qui peut être complexe pour les cas d'utilisation simples ou pour les débutants. -
Cas d'utilisation :
Adapté aux applications nécessitant une logique de navigation sur mesure ou des scénarios de navigation très complexes.
GoRouter
-
Bibliothèque tierce :
Fournit une couche d’abstraction au-dessus de Navigator 2.0 pour simplifier la configuration des routes. -
Simplicité de configuration :
Utilise une syntaxe déclarative simplifiée pour définir les routes et gère automatiquement le deep linking et la mise à jour de l'URL, ce qui réduit le code à écrire. -
Productivité accrue :
Réduit la complexité du code de navigation, permettant aux développeurs de se concentrer davantage sur les fonctionnalités de leur application. -
Cas d'utilisation :
Idéal pour la plupart des applications courantes où une navigation simple et efficace est requise, sans avoir besoin d'un contrôle ultra-précis.
Guide Étape par Étape : Navigation avec Flutter (Navigator 2.0 et GoRouter)
Ce guide vous montre comment mettre en place la navigation dans une application Flutter en utilisant deux approches : Navigator 2.0 (la solution native) et GoRouter (une bibliothèque qui simplifie la navigation). Vous trouverez ci-dessous toutes les étapes pour créer et configurer votre projet.
Étape 1 : Créer un Nouveau Projet Flutter
Étape 2 : Organiser la Structure du Projet
Pour mieux organiser votre code, vous pouvez créer plusieurs fichiers :
-
main.dart
: Point d'entrée de l'application et configuration du routeur. -
screens.dart
: Contiendra les widgetsHomeScreen
etDetailScreen
. - (Pour Navigator 2.0)
app_state.dart
: Modèle d’état de navigation. - (Pour Navigator 2.0)
my_router_delegate.dart
: Implémentation personnalisée du RouterDelegate. - (Pour Navigator 2.0)
my_route_information_parser.dart
: Conversion de l’URL en configuration de navigation.
Étape 3 : Implémentation avec Navigator 2.0
-
3.1 Créer le Modèle d’État
Créez un fichier app_state.dart
et ajoutez-y le code suivant pour gérer l’état de navigation :
// app_state.dart
import 'package:flutter/material.dart';
enum AppPage { home, detail }
class AppState extends ChangeNotifier {
AppPage _selectedPage = AppPage.home;
AppPage get selectedPage => _selectedPage;
void goTo(AppPage page) {
_selectedPage = page;
notifyListeners();
}
}
-
3.2 Créer le RouterDelegate
Créez un fichier my_router_delegate.dart
pour définir le comportement de la navigation :
// my_router_delegate.dart
import 'package:flutter/material.dart';
import 'app_state.dart';
import 'screens.dart';
class MyRouterDelegate extends RouterDelegate<AppPage>
with ChangeNotifier, PopNavigatorRouterDelegateMixin<AppPage> {
final GlobalKey<NavigatorState> navigatorKey;
final AppState appState;
MyRouterDelegate(this.appState)
: navigatorKey = GlobalKey<NavigatorState>() {
appState.addListener(notifyListeners);
}
@override
AppPage? get currentConfiguration => appState.selectedPage;
@override
Widget build(BuildContext context) {
return Navigator(
key: navigatorKey,
pages: [
MaterialPage(
child: HomeScreen(
onNavigate: () => appState.goTo(AppPage.detail),
),
),
if (appState.selectedPage == AppPage.detail)
MaterialPage(
child: DetailScreen(
onBack: () => appState.goTo(AppPage.home),
),
),
],
onPopPage: (route, result) {
if (!route.didPop(result)) return false;
appState.goTo(AppPage.home);
return true;
},
);
}
@override
Future<void> setNewRoutePath(AppPage configuration) async {
appState.goTo(configuration);
}
}
-
3.3 Créer le RouteInformationParser
Créez un fichier my_route_information_parser.dart
pour convertir les URL en état de navigation :
// my_route_information_parser.dart
import 'package:flutter/material.dart';
import 'app_state.dart';
class MyRouteInformationParser extends RouteInformationParser<AppPage> {
@override
Future<AppPage> parseRouteInformation(
RouteInformation routeInformation) async {
final uri = Uri.parse(routeInformation.location ?? '');
if (uri.pathSegments.contains('detail')) {
return AppPage.detail;
}
return AppPage.home;
}
@override
RouteInformation? restoreRouteInformation(AppPage configuration) {
switch (configuration) {
case AppPage.detail:
return const RouteInformation(location: '/detail');
case AppPage.home:
default:
return const RouteInformation(location: '/');
}
}
}
-
3.4 Créer les Écrans
Créez un fichier screens.dart et ajoutez les widgets pour vos deux écrans :
// screens.dart
import 'package:flutter/material.dart';
class HomeScreen extends StatelessWidget {
final VoidCallback onNavigate;
const HomeScreen({Key? key, required this.onNavigate}) : super(key: key);
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(title: const Text('Accueil')),
body: Center(
child: ElevatedButton(
onPressed: onNavigate,
child: const Text('Aller au détail'),
),
),
);
}
}
class DetailScreen extends StatelessWidget {
final VoidCallback onBack;
const DetailScreen({Key? key, required this.onBack}) : super(key: key);
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: const Text('Détail'),
leading: BackButton(onPressed: onBack),
),
body: const Center(child: Text('Page de détail')),
);
}
}
-
3.5 Configurer main.dart pour Navigator 2.0
Modifiez votre main.dart afin d’utiliser Navigator 2.0 :
// main.dart
import 'package:flutter/material.dart';
import 'app_state.dart';
import 'my_router_delegate.dart';
import 'my_route_information_parser.dart';
void main() {
runApp(const MyApp());
}
class MyApp extends StatelessWidget {
const MyApp({super.key});
@override
Widget build(BuildContext context) {
final appState = AppState();
return MaterialApp.router(
title: 'Demo Navigator 2.0',
routerDelegate: MyRouterDelegate(appState),
routeInformationParser: MyRouteInformationParser(),
);
}
}
Étape 4 : Implémentation avec GoRouter
Si vous préférez une configuration plus simple, vous pouvez utiliser GoRouter. Pour cela, modifiez (ou créez) le fichier main.dart
de la manière suivante :
- Ajouter la dépendance GoRouter
Dans votre
pubspec.yaml
, ajoutez :
dependencies:
flutter:
sdk: flutter
go_router: ^7.0.1
- Configurer GoRouter dans
main.dart
:
// main.dart
import 'package:flutter/material.dart';
import 'package:go_router/go_router.dart';
import 'screens.dart';
void main() {
runApp(const MyApp());
}
class MyApp extends StatelessWidget {
const MyApp({super.key});
@override
Widget build(BuildContext context) {
final GoRouter _router = GoRouter(
routes: [
GoRoute(
path: '/',
builder: (context, state) => HomeScreen(
onNavigate: () => context.go('/detail'),
),
),
GoRoute(
path: '/detail',
builder: (context, state) => DetailScreen(
onBack: () => context.pop(),
),
),
],
);
return MaterialApp.router(
title: 'Demo GoRouter',
routerConfig: _router,
);
}
}
Étape 5 : Tester l'Application
Conclusion
- Navigator 2.0 est parfait si vous avez besoin d'un contrôle fin sur la navigation et que vous êtes à l'aise avec une configuration plus complexe.
- GoRouter est recommandé pour ceux qui souhaitent une solution rapide, simple et efficace pour gérer la navigation, tout en bénéficiant des avantages du deep linking et d'une gestion de routes facilitée.
En résumé, choisissez Navigator 2.0 pour la flexibilité maximale et GoRouter pour la simplicité et la rapidité de mise en œuvre.
Références
- Flutter Navigation Documentation. https://docs.flutter.dev/development/ui/navigation (Consulté le 12 Mars 2025)
- GoRouter sur pub.dev. https://pub.dev/packages/go_router (Consulté le 12 Mars 2025)
- Navigator 2.0 API Documentation. https://api.flutter.dev/flutter/widgets/Navigator-class.html (Consulté le 11 Mars 2025)
Commentaires2
Question
Super article, j'ai bien appris aujourd'hui
Est-ce possible de définir des routes dynamiques dans Flutter, où le nom de la route pourrait être déterminé par une donnée en temps réel (par exemple, un ID ou un paramètre spécifique) plutôt que d’être codé en dur ?
Oui, c'est possible, il y a…
Oui, c'est possible, il y a un widget qui s'appelle MaterialApp contient une fonction qui s'appelle onGenerateRoute. Cette fonction permet d’intercepter la navigation et de créer la page à afficher en fonction du nom de la route reçu.