元素码农
基础
UML建模
数据结构
算法
设计模式
网络
TCP/IP协议
HTTPS安全机制
WebSocket实时通信
数据库
sqlite
postgresql
clickhouse
后端
rust
go
java
php
mysql
redis
mongodb
etcd
nats
zincsearch
前端
浏览器
javascript
typescript
vue3
react
游戏
unity
unreal
C++
C#
Lua
App
android
ios
flutter
react-native
安全
Web安全
测试
软件测试
自动化测试 - Playwright
人工智能
Python
langChain
langGraph
运维
linux
docker
工具
git
svn
🌞
🌙
目录
▶
Flutter基础
环境搭建与第一个应用
Dart语言快速入门
Flutter项目结构解析
▶
Widgets与布局
常用Widgets介绍
布局Widgets详解
自定义Widget创建
▶
状态管理
StatefulWidget与状态管理基础
Provider状态管理实战
BLoC模式入门
▶
导航与路由
页面导航基础
命名路由与参数传递
底部导航栏实现
▶
网络与数据存储
HTTP请求与Dio库使用
本地存储(SharedPreferences/SQLite)
Firebase集成指南
▶
打包与发布
Android应用打包
iOS应用打包
应用发布到商店指南
发布时间:
2025-03-22 22:15
↑
☰
# Flutter命名路由与参数传递 ## 什么是命名路由? 命名路由是一种通过字符串标识符来定义和访问应用程序页面的方式。相比于直接使用Widget实例进行导航,命名路由提供了以下优势: - 路由集中管理,便于维护 - 代码更清晰,路由逻辑与UI分离 - 支持深层链接(Deep Linking) - 便于实现动态路由 ## 配置命名路由 ### 基本配置 ```dart MaterialApp( title: 'Named Routes Demo', initialRoute: '/', // 初始路由 routes: { '/': (context) => HomeScreen(), '/details': (context) => DetailsScreen(), '/settings': (context) => SettingsScreen(), }, ) ``` ### 使用onGenerateRoute ```dart MaterialApp( onGenerateRoute: (settings) { // 解析路由名称和参数 if (settings.name == '/product') { final args = settings.arguments as Map<String, dynamic>; return MaterialPageRoute( builder: (context) => ProductScreen( productId: args['productId'], productName: args['productName'], ), ); } // 处理未知路由 return MaterialPageRoute( builder: (context) => UnknownScreen(), ); }, ) ``` ## 路由导航 ### 基本导航 ```dart // 导航到命名路由 ElevatedButton( onPressed: () { Navigator.pushNamed(context, '/details'); }, child: Text('查看详情'), ) // 返回上一页 ElevatedButton( onPressed: () { Navigator.pop(context); }, child: Text('返回'), ) ``` ### 导航方法 ```dart // 替换当前页面 Navigator.pushReplacementNamed( context, '/login', ) // 清空路由栈并导航 Navigator.pushNamedAndRemoveUntil( context, '/home', (route) => false, ) // 替换路由栈中的多个页面 Navigator.pushNamedAndRemoveUntil( context, '/details', ModalRoute.withName('/home'), // 保留到home页面 ) ``` ## 参数传递 ### 传递参数 ```dart // 传递单个参数 Navigator.pushNamed( context, '/details', arguments: 'Simple Parameter', ); // 传递多个参数 Navigator.pushNamed( context, '/product', arguments: { 'productId': '123', 'productName': 'Flutter Book', 'price': 29.99, }, ); ``` ### 接收参数 ```dart class ProductScreen extends StatelessWidget { @override Widget build(BuildContext context) { // 获取路由参数 final args = ModalRoute.of(context)!.settings.arguments as Map<String, dynamic>; return Scaffold( appBar: AppBar( title: Text(args['productName']), ), body: Center( child: Column( mainAxisAlignment: MainAxisAlignment.center, children: [ Text('Product ID: ${args['productId']}'), Text('Price: \$${args['price']}'), ], ), ), ); } } ``` ## 类型安全的参数传递 ### 定义路由参数类 ```dart class ProductRouteArgs { final String productId; final String productName; final double price; ProductRouteArgs({ required this.productId, required this.productName, required this.price, }); } // 使用参数类 Navigator.pushNamed( context, '/product', arguments: ProductRouteArgs( productId: '123', productName: 'Flutter Book', price: 29.99, ), ); // 在目标页面使用 class ProductScreen extends StatelessWidget { @override Widget build(BuildContext context) { final args = ModalRoute.of(context)!.settings.arguments as ProductRouteArgs; return Scaffold( appBar: AppBar(title: Text(args.productName)), body: Center( child: Column( mainAxisAlignment: MainAxisAlignment.center, children: [ Text('Product ID: ${args.productId}'), Text('Price: \$${args.price}'), ], ), ), ); } } ``` ## 动态路由生成 ### 路由模式匹配 ```dart MaterialApp( onGenerateRoute: (settings) { // 使用正则表达式匹配路由 final productPattern = RegExp(r'^/product/([\w-]+)$'); final match = productPattern.firstMatch(settings.name ?? ''); if (match != null) { final productId = match.group(1); return MaterialPageRoute( builder: (context) => ProductScreen(productId: productId!), ); } // 处理其他路由 switch (settings.name) { case '/': return MaterialPageRoute(builder: (context) => HomeScreen()); case '/settings': return MaterialPageRoute(builder: (context) => SettingsScreen()); default: return MaterialPageRoute(builder: (context) => UnknownScreen()); } }, ) ``` ### 路由中间件 ```dart class AuthMiddleware extends RouteObserver<PageRoute<dynamic>> { @override void didPush(Route<dynamic> route, Route<dynamic>? previousRoute) { super.didPush(route, previousRoute); if (route.settings.name == '/profile') { // 检查用户是否登录 if (!isUserLoggedIn()) { // 重定向到登录页面 Navigator.pushReplacementNamed(route.navigator!.context, '/login'); } } } } // 在MaterialApp中使用中间件 MaterialApp( navigatorObservers: [AuthMiddleware()], // ... ) ``` ## 最佳实践 ### 1. 路由常量定义 ```dart // routes.dart class Routes { static const String home = '/'; static const String login = '/login'; static const String profile = '/profile'; static const String settings = '/settings'; static const String productDetails = '/product'; } // 使用常量 Navigator.pushNamed(context, Routes.profile); ``` ### 2. 路由生成器封装 ```dart class AppRouter { static Route<dynamic> generateRoute(RouteSettings settings) { switch (settings.name) { case Routes.home: return MaterialPageRoute(builder: (_) => HomeScreen()); case Routes.profile: return MaterialPageRoute(builder: (_) => ProfileScreen()); case Routes.productDetails: final args = settings.arguments as ProductRouteArgs; return MaterialPageRoute( builder: (_) => ProductScreen( productId: args.productId, productName: args.productName, ), ); default: return MaterialPageRoute( builder: (_) => UnknownScreen(), ); } } } // 在MaterialApp中使用 MaterialApp( onGenerateRoute: AppRouter.generateRoute, ) ``` ### 3. 参数验证 ```dart class ProductScreen extends StatelessWidget { final String productId; final String productName; const ProductScreen({ super.key, required this.productId, required this.productName, }) : assert(productId.isNotEmpty, 'Product ID cannot be empty'); @override Widget build(BuildContext context) { // ... } } ``` ### 4. 错误处理 ```dart MaterialApp( onGenerateRoute: (settings) { try { // 路由生成逻辑 return AppRouter.generateRoute(settings); } catch (e) { // 记录错误 print('Route error: $e'); // 返回错误页面 return MaterialPageRoute( builder: (_) => ErrorScreen( message: '页面加载失败', error: e.toString(), ), ); } }, ) ``` ## 总结 本文详细介绍了Flutter中命名路由和参数传递的使用方法,包括: 1. 命名路由的配置和基本使用 2. 不同的导航方法和场景 3. 参数传递的多种方式 4. 类型安全的参数传递 5. 动态路由生成和中间件 6. 最佳实践和注意事项 建议: - 使用常量管理路由名称 - 实现类型安全的参数传递 - 合理使用路由中间件 - 做好错误处理和参数验证 - 保持路由逻辑的清晰和可维护性