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

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

相关推荐
独特的螺狮粉7 小时前
开源鸿蒙跨平台Flutter开发:微波射频阻抗匹配系统-极坐标史密斯圆图与天线信号渲染架构
开发语言·flutter·华为·架构·开源·harmonyos
冰暮流星7 小时前
javascript之dom方法访问内容
开发语言·前端·javascript
小雨天気.7 小时前
Flutter 框架跨平台鸿蒙开发 - 选择困难终结者应用
flutter·华为·生活·harmonyos·鸿蒙
有意义7 小时前
滴滴一面复盘:从CSS布局到TS核心思想
前端·面试
竹林8187 小时前
React + wagmi 实战:从零构建一个能“读”能“写”的 DeFi 前端,我踩了这些坑
前端·javascript
我命由我123457 小时前
在 React 项目中,配置了 setupProxy.js 文件,无法正常访问 http://localhost:3000
开发语言·前端·javascript·react.js·前端框架·ecmascript·js
俺不会敲代码啊啊啊7 小时前
封装 ECharts Hook 适配多种图表容器
前端·vue.js·typescript·echarts
J2虾虾7 小时前
在Vue3中推荐使用的函数定义方法
前端·javascript·vue.js
辻戋7 小时前
从零手写mini-react
javascript·react.js·ecmascript
3秒一个大7 小时前
Cookie/Session vs JWT 双 Token:登录认证方案的演进与对比
前端·安全·ajax