Implémentation du routage et du deep linking
Contenu
- Concepts fondamentaux
- Workflow : Initialiser l'application et le routeur
- Workflow : Configurer le deep linking multiplateforme
- Workflow : Implémenter 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 qui définit l'arbre des routes de l'application.
- GoRoute : Une route standard qui associe un chemin URL à un écran Flutter.
- ShellRoute / StatefulShellRoute : Enveloppe les routes enfants dans une coque UI 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 : Initialiser l'application et le routeur
Suivez ce workflow pour démarrer 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 et le deep linking.
- [ ] Implémenter la configuration
GoRouter. - [ ] Lier le routeur à
MaterialApp.router.
1. Créer le squelette de 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 l'authentification ou le routage basé sur l'état en utilisant le 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() {
// Use path URL strategy to remove the '#' from web URLs
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 : Configurer le deep linking multiplateforme
Configurez les plateformes natives pour intercepter des URLs spécifiques et les router dans 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 vous configurez 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 à l'adressehttps://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 vous configurez pour iOS :
- Modifier
Info.plist: Acceptez le gestionnaire de deep linking par défaut de Flutter. Remarque : Si vous utilisez un plugin de deep linking tiers (par exemple,app_links), définissez cette valeur 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) à l'adressehttps://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 lancé.xcrun simctl openurl booted https://yourdomain.com/details/123
Workflow : Implémenter la navigation imbriquée
Utilisez StatefulShellRoute pour implémenter des coques UI 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 configurationGoRouter. - [ ] Créer des instances
StatefulShellBranchpour chaque onglet de navigation. - [ ] Implémenter le widget de coque 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 de widget de coque haute fidélité
Implémentez la coque UI qui consomme StatefulNavigationShell pour gérer la commutation de branches.
class ScaffoldWithNavBar extends StatelessWidget {
const ScaffoldWithNavBar({
required this.navigationShell,
super.key,
});
final StatefulNavigationShell navigationShell;
void _goBranch(int index) {
navigationShell.goBranch(
index,
// Support navigating to the initial location when tapping the active tab.
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.
// Replaces the current route stack with the target route (Declarative)
context.go('/details/123');
// Pushes the target route onto the existing stack (Imperative)
context.push('/details/123');
// Navigates using a named route and path parameters
context.goNamed('details', pathParameters: {'id': '123'});
// Pops the current route
context.pop();