深入解析 Flutter 高级路由管理:使用 go_router
和 auto_route
实现复杂路由与拦截
在 Flutter 中,随着应用规模的增长,路由管理变得越来越复杂。简单的 Navigator
和命名路由可能难以满足需求,比如嵌套路由、动态路由参数、路由守卫(如登录验证)等。为了解决这些问题,Flutter 社区提供了强大的第三方路由库,如 go_router
和 auto_route
。
本篇博客将深入探讨如何使用 go_router
和 auto_route
实现复杂路由管理,并结合实际场景实现路由拦截(如登录验证)。
1. 为什么需要高级路由管理?
1.1 内置路由的局限性
- 嵌套路由难以管理:内置路由不支持嵌套路由,需要手动处理页面跳转逻辑。
- 缺乏路由守卫:无法轻松实现路由拦截(如登录验证)。
- 动态路由参数处理复杂:需要手动解析和传递参数。
1.2 第三方路由库的优势
- 嵌套路由:支持多级嵌套路由,简化复杂页面结构的管理。
- 动态路由参数:轻松处理动态参数和查询参数。
- 路由守卫:提供路由拦截功能,支持登录验证、权限控制等。
- 代码简洁:通过声明式路由配置,减少样板代码。
2. 使用 go_router
实现复杂路由管理
2.1 什么是 go_router
?
go_router
是一个轻量级的路由库,专为 Flutter 设计,支持嵌套路由、动态路由参数和路由守卫。
2.2 安装 go_router
在 pubspec.yaml
中添加依赖:
dependencies:go_router: ^6.0.0
运行以下命令安装依赖:
flutter pub get
2.3 基本用法
路由配置
使用 GoRouter
配置路由表:
import 'package:flutter/material.dart';
import 'package:go_router/go_router.dart';void main() {runApp(MyApp());
}class MyApp extends StatelessWidget {final GoRouter _router = GoRouter(initialLocation: '/',routes: [GoRoute(path: '/',builder: (context, state) => HomePage(),),GoRoute(path: '/details/:id',builder: (context, state) {final id = state.params['id']!;return DetailsPage(id: id);},),],);Widget build(BuildContext context) {return MaterialApp.router(routerConfig: _router,);}
}class HomePage extends StatelessWidget {Widget build(BuildContext context) {return Scaffold(appBar: AppBar(title: Text("首页")),body: ListView(children: [ListTile(title: Text("详情页 1"),onTap: () => context.go('/details/1'),),ListTile(title: Text("详情页 2"),onTap: () => context.go('/details/2'),),],),);}
}class DetailsPage extends StatelessWidget {final String id;DetailsPage({required this.id});Widget build(BuildContext context) {return Scaffold(appBar: AppBar(title: Text("详情页")),body: Center(child: Text("详情页 ID: $id"),),);}
}
代码解析
GoRouter
:定义路由表,配置路径和页面。- 动态路由参数:通过
state.params
获取动态参数。 context.go
:实现页面跳转。
2.4 嵌套路由
场景
在电商应用中,商品详情页可能包含多个子页面(如商品信息、评论、推荐)。
实现嵌套路由
final GoRouter _router = GoRouter(initialLocation: '/',routes: [GoRoute(path: '/',builder: (context, state) => HomePage(),routes: [GoRoute(path: 'details/:id',builder: (context, state) {final id = state.params['id']!;return DetailsPage(id: id);},routes: [GoRoute(path: 'reviews',builder: (context, state) => ReviewsPage(),),],),],),],
);
跳转到嵌套路由
context.go('/details/1/reviews');
2.5 路由拦截(登录验证)
场景
某些页面(如购物车、订单)需要登录后才能访问。
实现路由拦截
bool isLoggedIn = false;final GoRouter _router = GoRouter(initialLocation: '/',routes: [GoRoute(path: '/',builder: (context, state) => HomePage(),),GoRoute(path: '/cart',builder: (context, state) => CartPage(),redirect: (context, state) {if (!isLoggedIn) {return '/login';}return null;},),GoRoute(path: '/login',builder: (context, state) => LoginPage(),),],
);
代码解析
redirect
:在路由跳转前检查登录状态。- 未登录时重定向:将用户重定向到登录页面。
3. 使用 auto_route
实现复杂路由管理
3.1 什么是 auto_route
?
auto_route
是一个功能强大的路由库,支持代码生成、嵌套路由和路由守卫。
3.2 安装 auto_route
在 pubspec.yaml
中添加依赖:
dependencies:auto_route: ^5.0.0auto_route_generator: ^5.0.0
dev_dependencies:build_runner: ^2.0.0
运行以下命令安装依赖:
flutter pub get
3.3 基本用法
定义路由表
使用 @MaterialAutoRouter
注解定义路由表:
import 'package:auto_route/auto_route.dart';
import 'package:flutter/material.dart';(routes: <AutoRoute>[AutoRoute(page: HomePage, initial: true),AutoRoute(page: DetailsPage),],
)
class $AppRouter {}
生成路由代码
运行以下命令生成路由代码:
flutter pub run build_runner build
使用路由
final _appRouter = AppRouter();
Widget build(BuildContext context) {return MaterialApp.router(routerDelegate: _appRouter.delegate(),routeInformationParser: _appRouter.defaultRouteParser(),);
}
3.4 路由守卫(登录验证)
实现路由守卫
class AuthGuard extends AutoRouteGuard {final bool isLoggedIn;AuthGuard(this.isLoggedIn);void onNavigation(NavigationResolver resolver, StackRouter router) {if (isLoggedIn) {resolver.next(true); // 允许导航} else {router.push(LoginRoute()); // 跳转到登录页面}}
}
配置路由守卫
(routes: <AutoRoute>[AutoRoute(page: HomePage, initial: true),AutoRoute(page: CartPage, guards: [AuthGuard]),AutoRoute(page: LoginPage),],
)
class $AppRouter {}
4. 项目实战:实现一个多页面应用
4.1 功能需求
- 首页:展示商品列表。
- 商品详情页:展示商品详情。
- 购物车页:需要登录后才能访问。
4.2 使用 go_router
实现
完整代码
bool isLoggedIn = false;final GoRouter _router = GoRouter(initialLocation: '/',routes: [GoRoute(path: '/',builder: (context, state) => HomePage(),),GoRoute(path: '/details/:id',builder: (context, state) {final id = state.params['id']!;return DetailsPage(id: id);},),GoRoute(path: '/cart',builder: (context, state) => CartPage(),redirect: (context, state) {if (!isLoggedIn) {return '/login';}return null;},),GoRoute(path: '/login',builder: (context, state) => LoginPage(),),],
);
总结
-
go_router
和auto_route
的对比go_router
:轻量级,适合快速开发。auto_route
:功能强大,适合复杂项目。
-
高级功能
- 嵌套路由:简化复杂页面结构。
- 路由守卫:实现登录验证和权限控制。
-
项目实战
- 通过路由设计和守卫功能,构建一个多页面应用。