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支持好

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

相关推荐
程序员Sunday7 小时前
JavaScript 事件循环面试题,宏任务与微任务怎么执行|Sunday面试指南
开发语言·javascript·面试·校招·事件循环·程序员sunday
Setsuna_F_Seiei8 小时前
前端转型 Agent 开发 06 之 Agent Memory 记忆系统(让 Agent 更智能,更懂你)
前端·agent·ai编程
zhangzeyuaaa8 小时前
Ruby 多线程、GVL(GIL)与 Mutex 完全指南
开发语言·前端·ruby
默_笙9 小时前
🌊 向量库和 ES 都查不出"关系",我只好给奶茶建了一张人脉网
前端·javascript
优选资讯9 小时前
标签打印软件怎么对接 Excel 数据
前端·excel
思无邪6610 小时前
用 AI 做 JS 逆向:从抓包到复现的完整方法论
开发语言·javascript·人工智能
一个风轻云淡10 小时前
GCC 和 GDB命令简单解读
java·linux·前端
u01110267511 小时前
图片处理接口如何统一错误信息 前端提示与后端错误码设计
前端·状态模式
福兮说11 小时前
浏览器里把 iPhone 的 HEIC 转成 JPG:Chrome 解不开、转完大了七成、拍摄时间全丢,六个坑实测
前端·javascript·图像处理·chrome·ios·iphone·heic
libokaifa11 小时前
把语音模型塞进手机:sherpa-onnx 在 Android 上的 ASR / TTS
前端