Flutter第三方常用组件包之路由管理

Flutter第三方路由管理包详解

路由管理是Flutter应用开发中的核心功能。除了Flutter自带的路由系统,第三方路由包提供了更强大、便捷的功能。以下是目前流行的第三方路由管理包及其详细使用指南。

1. GetX路由管理

简介

GetX是一个轻量级但功能强大的Flutter包,除了路由管理还包含状态管理和依赖注入。

安装

yaml 复制代码
dependencies:
get: ^4.6.5

基本使用

dart 复制代码
import 'package:get/get.dart';

// 主函数
void main() {
runApp(MyApp());
}

class MyApp extends StatelessWidget {
@override
Widget build(BuildContext context) {
return GetMaterialApp(
// 使用GetMaterialApp替代MaterialApp
title: 'GetX路由示例',
initialRoute: '/',
getPages: [
GetPage(name: '/', page: () => HomePage()),
GetPage(name: '/details', page: () => DetailsPage()),
GetPage(
name: '/profile/:userId',
page: () => ProfilePage(),
),
],
);
}
}

// 页面定义
class HomePage extends StatelessWidget {
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(title: Text('首页')),
body: Center(
child: Column(
children: [
ElevatedButton(
onPressed: () {
// 普通跳转
Get.to(() => DetailsPage());
},
child: Text('跳转到详情页'),
),
ElevatedButton(
onPressed: () {
// 命名路由跳转
Get.toNamed('/details');
},
child: Text('命名路由跳转'),
),
ElevatedButton(
onPressed: () {
// 带参数跳转
Get.toNamed('/profile/123');
},
child: Text('带参数跳转'),
),
ElevatedButton(
onPressed: () {
// 返回并带结果
Get.back(result: '返回的数据');
},
child: Text('返回'),
),
ElevatedButton(
onPressed: () {
// 替换当前路由
Get.off(() => DetailsPage());
},
child: Text('替换路由'),
),
ElevatedButton(
onPressed: () {
// 清空路由栈并跳转
Get.offAll(() => DetailsPage());
},
child: Text('清空栈并跳转'),
),
],
),
),
);
}
}

// 详情页
class DetailsPage extends StatelessWidget {
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(title: Text('详情页')),
body: Center(
child: Column(
children: [
Text('详情页内容'),
ElevatedButton(
onPressed: () {
// 返回并带参数
Get.back(result: '详情页返回');
},
child: Text('返回首页'),
),
],
),
),
);
}
}

// 带参数的页面
class ProfilePage extends StatelessWidget {
@override
Widget build(BuildContext context) {
// 获取路由参数
final userId = Get.parameters['userId'];

return Scaffold(
appBar: AppBar(title: Text('用户资料: $userId')),
body: Center(
child: Text('用户ID: $userId'),
),
);
}
}

高级功能

dart 复制代码
// 1. 中间件(路由守卫)
class AuthMiddleware extends GetMiddleware {
@override
RouteSettings? redirect(String? route) {
// 检查用户是否登录
bool isLoggedIn = false; // 这里替换为实际的登录检查

if (!isLoggedIn && route == '/profile') {
// 未登录,重定向到登录页
return RouteSettings(name: '/login');
}
return null;
}

@override
GetPage? onPageCalled(GetPage? page) {
print('路由被调用: ${page?.name}');
return super.onPageCalled(page);
}
}

// 在路由配置中使用中间件
getPages: [
GetPage(
name: '/profile',
page: () => ProfilePage(),
middlewares: [AuthMiddleware()],
),
];

// 2. 传参的多种方式
// 方式一:URL参数
Get.toNamed('/profile/123');

// 方式二:参数对象
Get.toNamed('/profile', arguments: {
'userId': '123',
'name': '张三'
});

// 在目标页面获取参数
class ProfilePage extends StatelessWidget {
@override
Widget build(BuildContext context) {
final arguments = Get.arguments; // 获取传递的参数

return Scaffold(
appBar: AppBar(
title: Text(arguments['name'] ?? '用户资料'),
),
body: Center(
child: Text('用户ID: ${arguments['userId']}'),
),
);
}
}

// 3. 路由观察者
Get.config(
enableLog: true,
logWriterCallback: (text, {bool isError = false}) {
print('路由日志: $text');
},
);

路由动画

dart 复制代码
// 自定义转场动画
Get.to(
DetailsPage(),
transition: Transition.fadeIn, // 渐变
duration: Duration(milliseconds: 300),
);

// 更多动画类型
Get.to(
DetailsPage(),
transition: Transition.cupertino, // iOS风格
);

Get.to(
DetailsPage(),
transition: Transition.zoom, // 缩放
);

Get.to(
DetailsPage(),
transition: Transition.downToUp, // 从下往上
);

// 自定义动画
Get.to(
DetailsPage(),
transition: Transition.circularReveal, // 圆形展开
curve: Curves.easeInOut,
duration: Duration(milliseconds: 500),
);

2. Auto Route

简介

基于代码生成的路由管理,类型安全,支持嵌套路由、守卫等。

安装

yaml 复制代码
dependencies:
auto_route: ^7.2.0

dev_dependencies:
auto_route_generator: ^7.2.0
build_runner: ^2.3.0

基本使用

dart 复制代码
// 1. 创建路由配置
// app_router.dart
import 'package:auto_route/auto_route.dart';
import 'package:flutter/material.dart';

part 'app_router.gr.dart';

@MaterialAutoRouter(
replaceInRouteName: 'Page,Route',
routes: <AutoRoute>[
AutoRoute(page: HomePage, initial: true),
AutoRoute(page: DetailsPage),
AutoRoute(page: ProfilePage, path: '/profile/:userId'),
AutoRoute(
page: SettingsPage,
children: [
AutoRoute(page: AccountPage, initial: true),
AutoRoute(page: NotificationPage),
AutoRoute(page: PrivacyPage),
],
),
],
)
class AppRouter extends _$AppRouter {}

// 2. 生成路由代码
// 运行命令:flutter packages pub run build_runner build

// 3. 在main.dart中使用
void main() {
runApp(MyApp());
}

class MyApp extends StatelessWidget {
final _appRouter = AppRouter();

@override
Widget build(BuildContext context) {
return MaterialApp.router(
title: 'AutoRoute示例',
routerDelegate: _appRouter.delegate(),
routeInformationParser: _appRouter.defaultRouteParser(),
);
}
}

// 4. 页面定义
@RoutePage()
class HomePage extends StatelessWidget {
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(title: Text('首页')),
body: Center(
child: Column(
children: [
ElevatedButton(
onPressed: () {
context.pushRoute(DetailsRoute());
},
child: Text('跳转到详情'),
),
ElevatedButton(
onPressed: () {
context.pushRoute(ProfileRoute(userId: '123'));
},
child: Text('用户资料'),
),
ElevatedButton(
onPressed: () {
context.pushRoute(SettingsRoute());
},
child: Text('设置(嵌套路由)'),
),
],
),
),
);
}
}

// 5. 带参数的页面
@RoutePage()
class ProfilePage extends StatelessWidget {
final String userId;

const ProfilePage({
@PathParam('userId') required this.userId,
});

@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(title: Text('用户: $userId')),
body: Center(
child: Text('用户ID: $userId'),
),
);
}
}

// 6. 查询参数
@RoutePage()
class SearchPage extends StatelessWidget {
final String? query;

const SearchPage({
@QueryParam('q') this.query,
});

@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(title: Text('搜索')),
body: Center(
child: Text('搜索词: ${query ?? "无"}'),
),
);
}
}

// 跳转时传递查询参数
context.pushRoute(SearchRoute(queryParams: {'q': 'flutter'}));

路由守卫

dart 复制代码
// 1. 创建守卫
class AuthGuard extends AutoRouteGuard {
@override
void onNavigation(NavigationResolver resolver, StackRouter router) {
bool isAuthenticated = false; // 检查登录状态

if (isAuthenticated) {
resolver.next(true); // 允许导航
} else {
// 重定向到登录页
router.push(LoginRoute(
onLoginResult: (success) {
if (success) {
resolver.next(true);
} else {
resolver.next(false);
}
},
));
}
}
}

// 2. 在路由配置中使用守卫
@MaterialAutoRouter(
replaceInRouteName: 'Page,Route',
routes: [
AutoRoute(page: HomePage, initial: true),
AutoRoute(
page: DashboardPage,
guards: [AuthGuard()], // 应用守卫
),
],
)
class AppRouter extends _$AppRouter {}

嵌套路由

dart 复制代码
// 1. 主页面结构
@RoutePage()
class MainPage extends StatelessWidget {
@override
Widget build(BuildContext context) {
return AutoTabsScaffold(
routes: [
HomeRoute(),
SearchRoute(),
ProfileRoute(),
],
bottomNavigationBuilder: (_, tabsRouter) {
return BottomNavigationBar(
currentIndex: tabsRouter.activeIndex,
onTap: tabsRouter.setActiveIndex,
items: [
BottomNavigationBarItem(icon: Icon(Icons.home), label: '首页'),
BottomNavigationBarItem(icon: Icon(Icons.search), label: '搜索'),
BottomNavigationBarItem(icon: Icon(Icons.person), label: '我的'),
],
);
},
);
}
}

3. Fluro

简介

功能丰富的路由框架,支持通配符、参数传递、中间件等。

安装

yaml 复制代码
dependencies:
fluro: ^2.0.5

基本使用

dart 复制代码
import 'package:flutter/material.dart';
import 'package:fluro/fluro.dart';

// 1. 创建路由器实例
final router = FluroRouter();

// 2. 定义路由处理器
void defineRoutes() {
// 首页
router.define(
'/',
handler: Handler(
handlerFunc: (context, parameters) {
return HomePage();
},
),
);

// 详情页
router.define(
'/details',
handler: Handler(
handlerFunc: (context, parameters) {
return DetailsPage();
},
),
);

// 带参数的页面
router.define(
'/user/:id',
handler: Handler(
handlerFunc: (context, parameters) {
String id = parameters['id']?.first ?? '';
return UserPage(userId: id);
},
),
);

// 可选参数
router.define(
'/search',
handler: Handler(
handlerFunc: (context, parameters) {
String? query = parameters['q']?.first;
return SearchPage(query: query);
},
),
);

// 通配符路由
router.define(
'/settings/*',
handler: Handler(
handlerFunc: (context, parameters) {
List<String>? path = parameters['*'];
return SettingsPage(path: path);
},
),
);
}

// 3. 在应用中使用
class MyApp extends StatelessWidget {
MyApp() {
defineRoutes();
}

@override
Widget build(BuildContext context) {
return MaterialApp(
title: 'Fluro示例',
onGenerateRoute: router.generator,
initialRoute: '/',
);
}
}

// 4. 页面导航
class HomePage extends StatelessWidget {
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(title: Text('首页')),
body: Center(
child: Column(
children: [
ElevatedButton(
onPressed: () {
// 跳转到详情页
router.navigateTo(context, '/details');
},
child: Text('详情页'),
),
ElevatedButton(
onPressed: () {
// 带参数跳转
router.navigateTo(
context,
'/user/123',
transition: TransitionType.cupertino,
);
},
child: Text('用户页'),
),
ElevatedButton(
onPressed: () {
// 带查询参数跳转
router.navigateTo(
context,
'/search?q=flutter',
);
},
child: Text('搜索页'),
),
ElevatedButton(
onPressed: () {
// 替换路由
router.navigateTo(
context,
'/details',
replace: true,
);
},
child: Text('替换路由'),
),
ElevatedButton(
onPressed: () {
// 清空栈
router.navigateTo(
context,
'/details',
clearStack: true,
);
},
child: Text('清空栈跳转'),
),
],
),
),
);
}
}

// 5. 中间件示例
class AuthMiddleware extends Handler {
@override
Future<bool> handle(
BuildContext context,
Map<String, List<String>> parameters,
RouteMatch match,
) async {
bool isLoggedIn = false; // 检查登录状态

if (!isLoggedIn && match.route.path == '/profile') {
// 重定向到登录页
router.navigateTo(context, '/login');
return false;
}
return true;
}
}

4. Go Router

简介

官方推荐的声明式路由包,支持Web和移动端。

安装

yaml 复制代码
dependencies:
go_router: ^10.0.0

基本使用

dart 复制代码
import 'package:flutter/material.dart';
import 'package:go_router/go_router.dart';

// 1. 创建路由配置
final GoRouter router = GoRouter(
routes: [
// 首页
GoRoute(
path: '/',
builder: (context, state) => HomePage(),
),

// 详情页
GoRoute(
path: '/details',
builder: (context, state) => DetailsPage(),
),

// 带参数的页面
GoRoute(
path: '/user/:id',
builder: (context, state) {
String id = state.params['id']!;
return UserPage(userId: id);
},
),

// 查询参数
GoRoute(
path: '/search',
builder: (context, state) {
String? query = state.queryParams['q'];
return SearchPage(query: query);
},
),

// 嵌套路由
ShellRoute(
builder: (context, state, child) {
return MainLayout(child: child);
},
routes: [
GoRoute(
path: '/dashboard',
builder: (context, state) => DashboardPage(),
routes: [
GoRoute(
path: 'settings',
builder: (context, state) => SettingsPage(),
),
],
),
],
),
],

// 错误页面
errorBuilder: (context, state) => ErrorPage(error: state.error),

// 重定向
redirect: (context, state) {
bool isLoggedIn = false;

// 检查是否访问需要登录的页面
if (state.location.startsWith('/profile') && !isLoggedIn) {
return '/login';
}

return null;
},
);

// 2. 在应用中使用
void main() {
runApp(MyApp());
}

class MyApp extends StatelessWidget {
@override
Widget build(BuildContext context) {
return MaterialApp.router(
title: 'GoRouter示例',
routerConfig: router,
);
}
}

// 3. 页面导航
class HomePage extends StatelessWidget {
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(title: Text('首页')),
body: Center(
child: Column(
children: [
ElevatedButton(
onPressed: () {
context.go('/details');
},
child: Text('跳转到详情页'),
),
ElevatedButton(
onPressed: () {
context.go('/user/123');
},
child: Text('用户资料'),
),
ElevatedButton(
onPressed: () {
context.go('/search?q=flutter');
},
child: Text('搜索'),
),
ElevatedButton(
onPressed: () {
context.go('/dashboard');
},
child: Text('仪表板(嵌套路由)'),
),
ElevatedButton(
onPressed: () {
// 替换当前路由
context.replace('/details');
},
child: Text('替换路由'),
),
],
),
),
);
}
}

// 4. 路由观察者
final GoRouter router = GoRouter(
routes: [...],
observers: [
MyRouteObserver(),
],
);

class MyRouteObserver extends NavigatorObserver {
@override
void didPush(Route<dynamic> route, Route<dynamic>? previousRoute) {
print('路由入栈: ${route.settings.name}');
}

@override
void didPop(Route<dynamic> route, Route<dynamic>? previousRoute) {
print('路由出栈: ${route.settings.name}');
}
}

5. 路由包对比与选择建议

特性 GetX AutoRoute Fluro GoRouter
学习曲线 简单 中等 中等 简单
类型安全
代码生成
Web支持 优秀
嵌套路由 支持 优秀 支持 优秀
路由守卫 支持 支持 支持 支持
参数传递 多种方式 类型安全 URL参数 类型安全
社区活跃 非常活跃 活跃 一般 非常活跃
维护状态 活跃 活跃 维护中 官方维护

选择建议

  1. 新手/快速开发 :推荐 GetX,学习成本低,功能全面
  2. 大型项目/团队协作 :推荐 AutoRoute,类型安全,维护性好
  3. Web项目 :推荐 GoRouter,官方维护,Web支持最好
  4. 已有项目迁移:如果已有Fluro项目可继续使用

6. 实际项目最佳实践

统一路由管理

dart 复制代码
// routes.dart - 统一管理路由
class Routes {
static const String home = '/';
static const String details = '/details';
static const String profile = '/profile/:id';
static const String settings = '/settings';
static const String login = '/login';

// 获取路径
static String profilePath(String id) => '/profile/$id';

// 命名路由映射
static Map<String, WidgetBuilder> getRoutes() {
return {
home: (context) => HomePage(),
details: (context) => DetailsPage(),
login: (context) => LoginPage(),
};
}
}

路由工具类

dart 复制代码
// router_utils.dart
class RouterUtils {
// 统一跳转方法
static void navigateTo(BuildContext context, String path, {
Map<String, String>? params,
Map<String, dynamic>? arguments,
bool replace = false,
}) {
if (replace) {
Navigator.pushReplacementNamed(context, path, arguments: arguments);
} else {
Navigator.pushNamed(context, path, arguments: arguments);
}
}

// 带返回结果的跳转
static Future<T?> navigateForResult<T>(
BuildContext context,
String path, {
Map<String, dynamic>? arguments,
}) async {
return await Navigator.pushNamed(
context,
path,
arguments: arguments,
);
}

// 清空栈跳转
static void navigateAndClearStack(
BuildContext context,
String path, {
Map<String, dynamic>? arguments,
}) {
Navigator.pushNamedAndRemoveUntil(
context,
path,
(route) => false,
arguments: arguments,
);
}
}

状态管理与路由结合

dart 复制代码
// 使用Provider + 路由
class AppState extends ChangeNotifier {
String? _authToken;

String? get authToken => _authToken;

void setAuthToken(String token) {
_authToken = token;
notifyListeners();
}

void logout() {
_authToken = null;
notifyListeners();
}
}

// 路由守卫
class AuthGuard extends GetMiddleware {
@override
RouteSettings? redirect(String? route) {
final appState = Get.find<AppState>();

if (!_isPublicRoute(route) && appState.authToken == null) {
return RouteSettings(name: Routes.login);
}

return null;
}

bool _isPublicRoute(String? route) {
final publicRoutes = [Routes.login, Routes.register];
return publicRoutes.contains(route);
}
}

总结

第三方路由包各有优势,选择取决于项目需求:

  1. GetX:适合快速开发,功能全面
  2. AutoRoute:适合大型项目,类型安全
  3. Fluro:功能丰富,灵活
  4. GoRouter:官方推荐,Web支持好

无论选择哪个包,都应保持路由管理的统一性和规范性,遵循最佳实践,确保应用的可维护性和扩展性。

相关推荐
滑雪的企鹅.37 分钟前
HTML头部元信息避坑指南大纲
前端·html
一拳不是超人39 分钟前
老婆天天吵吵要买塔罗牌,我直接用 AI 2 小时写了个在线塔罗牌
前端·ai编程
excel2 小时前
如何解决 Nuxt DevTools 中关于 unstorage 包的报错
前端
Rust研习社2 小时前
使用 Axum 构建高性能异步 Web 服务
开发语言·前端·网络·后端·http·rust
C澒3 小时前
AI 生码 - API2Code:接口智能匹配与 API 自动化生码全链路设计
前端·低代码·ai编程
浔川python社3 小时前
HTML头部元信息避坑指南技术文章大纲
前端·html
IT_陈寒3 小时前
SpringBoot配置加载顺序把我坑惨了
前端·人工智能·后端
maaath3 小时前
【maaath】Flutter for OpenHarmony 跨平台工程集成密码加密能力
flutter·华为·harmonyos
kyriewen3 小时前
Next.js部署:从本地跑得欢,到线上飞得稳
前端·react.js·next.js
Moment3 小时前
面试官:给 llm 传递上下文,有哪几个身份 role ❓❓❓
前端·后端·面试