Implémentation du Routage et du Deep Linking
Contenu
- Concepts fondamentaux
- Workflow : Initialisation de l'application et du routeur
- Workflow : Configuration du deep linking par plateforme
- Workflow : Implémentation de la navigation imbriquée
- Exemples
Concepts fondamentaux
Utilisez le package go_router pour le routage déclaratif dans Flutter. Il fournit une API robuste pour les scénarios de routage complexes, le deep linking et la navigation imbriquée.
- GoRouter : L'objet de configuration central définissant l'arborescence des routes de l'application.
- GoRoute : Une route standard mappant un chemin URL à un écran Flutter.
- ShellRoute / StatefulShellRoute : Enveloppe les routes enfants dans une coquille d'interface utilisateur persistante (par exemple, une
BottomNavigationBar).StatefulShellRoutemaintient l'état des branches de navigation parallèles. - Path URL Strategy : Supprime le fragment
#par défaut des URL web, essentiel pour un deep linking propre entre les plateformes.
Workflow : Initialisation de l'application et du routeur
Suivez ce workflow pour amorcer une nouvelle application Flutter avec go_router et configurer le mécanisme de routage racine.
Progression des tâches
- [ ] Créer l'application Flutter.
- [ ] Ajouter la dépendance
go_router. - [ ] Configurer la stratégie URL pour le web/deep linking.
- [ ] Implémenter la configuration de
GoRouter. - [ ] Lier le routeur à
MaterialApp.router.
1. Créer l'application
Exécutez les commandes suivantes pour créer l'application et ajouter le package de routage requis :
flutter create <app-name>
cd <app-name>
flutter pub add go_router
2. Configurer le routeur
Définissez une instance GoRouter au niveau supérieur. Gérez le routage basé sur l'authentification ou l'état à l'aide du paramètre redirect.
import 'package:flutter/material.dart';
import 'package:go_router/go_router.dart';
import 'package:flutter_web_plugins/url_strategy.dart';
void main() {
// Utilisez la stratégie URL path pour supprimer le '#' des URL web
usePathUrlStrategy();
runApp(const MyApp());
}
final GoRouter _router = GoRouter(
initialLocation: '/',
routes: [
GoRoute(
path: '/',
builder: (context, state) => const HomeScreen(),
routes: [
GoRoute(
path: 'details/:id',
builder: (context, state) => DetailsScreen(id: state.pathParameters['id']!),
),
],
),
],
errorBuilder: (context, state) => ErrorScreen(error: state.error),
);
class MyApp extends StatelessWidget {
const MyApp({super.key});
@override
Widget build(BuildContext context) {
return MaterialApp.router(
routerConfig: _router,
title: 'Routing App',
);
}
}
Workflow : Configuration du deep linking par plateforme
Configurez les plateformes natives pour intercepter les URL spécifiques et les router vers l'application Flutter.
Progression des tâches
- [ ] Déterminer les plateformes cibles (iOS, Android, ou les deux).
- [ ] Appliquer la configuration conditionnelle pour Android (Manifest + Asset Links).
- [ ] Appliquer la configuration conditionnelle pour iOS (Plist + Entitlements + AASA).
- [ ] Exécuter le validateur -> examiner les erreurs -> corriger.
Si configuration pour Android :
- Modifier
AndroidManifest.xml: Ajoutez le filtre d'intention à l'intérieur de la balise<activity>pour.MainActivity.<intent-filter android:autoVerify="true"> <action android:name="android.intent.action.VIEW" /> <category android:name="android.intent.category.DEFAULT" /> <category android:name="android.intent.category.BROWSABLE" /> <data android:scheme="http" android:host="yourdomain.com" /> <data android:scheme="https" /> </intent-filter> - Héberger
assetlinks.json: Servez le JSON suivant àhttps://yourdomain.com/.well-known/assetlinks.json.[{ "relation": ["delegate_permission/common.handle_all_urls"], "target": { "namespace": "android_app", "package_name": "com.yourcompany.yourapp", "sha256_cert_fingerprints": ["YOUR_SHA256_FINGERPRINT"] } }]
Si configuration pour iOS :
- Modifier
Info.plist: Optez pour le gestionnaire de deep link par défaut de Flutter. Remarque : Si vous utilisez un plugin de deep linking tiers (par exemple,app_links), définissez ceci surNOpour éviter les conflits.<key>FlutterDeepLinkingEnabled</key> <true/> - Modifier
Runner.entitlements: Ajoutez le domaine associé.<key>com.apple.developer.associated-domains</key> <array> <string>applinks:yourdomain.com</string> </array> - Héberger
apple-app-site-association: Servez le JSON suivant (sans extension.json) àhttps://yourdomain.com/.well-known/apple-app-site-association.{ "applinks": { "apps": [], "details": [{ "appIDs": ["TEAM_ID.com.yourcompany.yourapp"], "paths": ["*"], "components": [{"/": "/*"}] }] } }
Boucle de validation
Exécutez le validateur -> examinez les erreurs -> corrigez.
- Android : Testez avec ADB.
adb shell 'am start -a android.intent.action.VIEW -c android.intent.category.BROWSABLE -d "https://yourdomain.com/details/123"' com.yourcompany.yourapp - iOS : Testez avec
xcrunsur un simulateur en cours d'exécution.xcrun simctl openurl booted https://yourdomain.com/details/123
Workflow : Implémentation de la navigation imbriquée
Utilisez StatefulShellRoute pour implémenter des coquilles d'interface utilisateur persistantes (comme une barre de navigation inférieure) qui maintiennent l'état de leurs routes enfants.
Progression des tâches
- [ ] Définir
StatefulShellRoute.indexedStackdans la configuration deGoRouter. - [ ] Créer des instances
StatefulShellBranchpour chaque onglet de navigation. - [ ] Implémenter le widget de coquille en utilisant
StatefulNavigationShell.
final GoRouter _router = GoRouter(
initialLocation: '/home',
routes: [
StatefulShellRoute.indexedStack(
builder: (context, state, navigationShell) {
return ScaffoldWithNavBar(navigationShell: navigationShell);
},
branches: [
StatefulShellBranch(
routes: [
GoRoute(
path: '/home',
builder: (context, state) => const HomeScreen(),
),
],
),
StatefulShellBranch(
routes: [
GoRoute(
path: '/settings',
builder: (context, state) => const SettingsScreen(),
),
],
),
],
),
],
);
Exemples
Implémentation haute fidélité du widget de coquille
Implémentez la coquille d'interface utilisateur qui consomme StatefulNavigationShell pour gérer le changement de branches.
class ScaffoldWithNavBar extends StatelessWidget {
const ScaffoldWithNavBar({
required this.navigationShell,
super.key,
});
final StatefulNavigationShell navigationShell;
void _goBranch(int index) {
navigationShell.goBranch(
index,
// Supporte la navigation vers l'emplacement initial lors de l'appui sur l'onglet actif.
initialLocation: index == navigationShell.currentIndex,
);
}
@override
Widget build(BuildContext context) {
return Scaffold(
body: navigationShell,
bottomNavigationBar: NavigationBar(
selectedIndex: navigationShell.currentIndex,
onDestinationSelected: _goBranch,
destinations: const [
NavigationDestination(icon: Icon(Icons.home), label: 'Home'),
NavigationDestination(icon: Icon(Icons.settings), label: 'Settings'),
],
),
);
}
}
Navigation programmatique
Utilisez les méthodes d'extension context.go() et context.push() fournies par go_router.
// Remplace la pile de routes actuelle par la route cible (Déclaratif)
context.go('/details/123');
// Ajoute la route cible à la pile existante (Impératif)
context.push('/details/123');
// Navigue en utilisant une route nommée et des paramètres de chemin
context.goNamed('details', pathParameters: {'id': '123'});
// Dépile la route actuelle
context.pop();