目前很多资料都还集中在navigator1.0版本(包括国内某些大模型还在推这个,估计训练的资料还是旧版)。初学者感到困惑,故整理之~
🧭 结论
总的来说,路由方案经历了多次迭代,目前是Navigator 2.0 。
-
Navigator 1.0 时代的 API 比较原始,社区各自摸索出命令式写法 和 generateRoute 集中管理两条路。
-
Navigator 2.0 出来后底层 API 虽然更强大但写起来繁琐,官方随后封装了 go_router 来填平这个坑。
现在的稳定选型就是 go_router + 文件结构:
routers.dart作为入口,配置GoRouter实例routes.dart按模块拆分路径常量或GoRoute列表
这套结构对大型项目同样够用,因为 go_router 本身支持嵌套路由、重定向、守卫、ShellRoute 等复杂场景,拆模块只是组织代码的问题,不是能力上的限制。
前沿三个方案的关注点各有侧重:
go_router_builder------ 用代码生成取代手写字符串路由,类型安全,代价是要学注解+跑build_runnerautoRoute------ 内置路由守卫和鉴权拦截机制,安全需求强的 app 更适合go_router_sugar------ 纯语法糖,没有新能力,看项目风格取舍

🗺️ Flutter 路由技术演进全景图
| 阶段 | 核心技术 | 核心特点 | 当前状态 |
|---|---|---|---|
| Navigator 1.0 | 命令式 API (push/pop) + 静态路由表 (routes) + onGenerateRoute |
简单直接,适合小应用;但无法与系统路由(如浏览器URL)深度集成。 | 已过时,新项目不建议使用。 |
| Navigator 2.0 | Router + RouterDelegate + RouteInformationParser |
声明式、与系统深度集成,但API极其复杂,需手写大量样板代码。 | 底层基石,但不直接使用。 |
| 声明式封装时代 | go_router (官方推荐) / auto_route (社区流行) | 在 Navigator 2.0 之上封装,提供简洁声明式 API。 | 当前主流,生产项目首选。 |
| 类型安全增强时代 | go_router_builder / auto_route (自带生成器) / go_router_sugar | 在声明式基础上,通过代码生成实现完全类型安全,消除字符串路径。 | 前沿方案,大中型项目可渐进式引入。 |
Navigator 1.0
Navigator 1.0 声明式路由
dart
// lib/main.dart
MaterialApp(
initialRoute: '/login',
routes: {
'/login': (context) => LoginScreen(),
'/home': (context) => HomeScreen(),
},
)
局限性:
- 无法传递参数 :
routes表的值是一个固定的WidgetBuilder,无法动态传入arguments。 - 无法实现路由守卫 :比如"未登录时强制跳转登录页",需要在每个页面
initState里重复写逻辑。 - 无法处理未知路由 :用户输入
/abc会直接报错。
onGenerateRoute
onGenerateRoute是Navigator 1.0时代解决传参、守卫、404 页面等问题的方案
dart
MaterialApp(
initialRoute: '/',
onGenerateRoute: (settings) {
// 获取传递的参数
final args = settings.arguments;
// 路由守卫逻辑
final isLoggedIn = StorageUtils.getTokenSync(); // 假设你有同步读取方法
switch (settings.name) {
case '/':
return MaterialPageRoute(builder: (_) => const SplashScreen());
case '/login':
return MaterialPageRoute(builder: (_) => const LoginScreen());
case '/home':
if (!isLoggedIn) {
return MaterialPageRoute(builder: (_) => const LoginScreen());
}
return MaterialPageRoute(builder: (_) => const HomeScreen());
default:
return MaterialPageRoute(builder: (_) => const NotFoundScreen());
}
},
)
Navigator 2.0
Navigator 2.0 出来后底层 API 虽然更强大但写起来繁琐,官方随后封装了 go_router 来填平这个坑。
🧱 推荐的项目结构
bash
lib/
├── main.dart # 入口,只负责 runApp 和顶层 Provider
├── app.dart # MaterialApp.router 的主体(可选进一步拆分)
├── router/
│ ├── router.dart # GoRouter 实例和路由表定义
│ └── routes.dart # 路由路径常量(避免硬编码字符串)
├── screens/
│ ├── login_screen.dart
│ └── home_screen.dart
└── utils/
└── storage_utils.dart
📝 具体抽离示例
1. 路径常量文件 lib/router/routes.dart
dart
class AppRoutes {
static const String login = '/login';
static const String home = '/home';
// 后续可加:static String userDetails(String id) => '/user/$id';
}
2. 路由配置文件 lib/router/router.dart
dart
import 'package:flutter/material.dart';
import 'package:go_router/go_router.dart';
import '../screens/login_screen.dart';
import '../screens/home_screen.dart';
import '../utils/storage_utils.dart';
import 'routes.dart';
class AppRouter {
static final GoRouter router = GoRouter(
initialLocation: AppRoutes.login, // 初始值可动态计算,但建议在 redirect 中统一处理
routes: [
GoRoute(
path: AppRoutes.login,
builder: (context, state) => const LoginScreen(),
),
GoRoute(
path: AppRoutes.home,
builder: (context, state) => const HomeScreen(),
),
],
redirect: _redirect,
);
static Future<String?> _redirect(BuildContext context, GoRouterState state) async {
final token = await StorageUtils.getToken();
final isLoggedIn = token != null;
final isGoingToLogin = state.matchedLocation == AppRoutes.login;
// 未登录且不在登录页 → 强制去登录
if (!isLoggedIn && !isGoingToLogin) {
return AppRoutes.login;
}
// 已登录却要去登录页 → 重定向到首页
if (isLoggedIn && isGoingToLogin) {
return AppRoutes.home;
}
return null;
}
}
3. 简化后的 main.dart
dart
import 'package:flutter/material.dart';
import 'router/router.dart';
void main() {
runApp(const MyApp());
}
class MyApp extends StatelessWidget {
const MyApp({super.key});
@override
Widget build(BuildContext context) {
return MaterialApp.router(
title: 'Flutter Login Demo',
theme: ThemeData(primarySwatch: Colors.blue),
routerConfig: AppRouter.router,
);
}
}
未来关注方向
| 方案 | 定位 | 行动建议 |
|---|---|---|
go_router_builder |
go_router 官方增强插件,提供类型安全。 |
保持关注,当页面超过 50+ 或传参频繁出错时,可平滑迁移。 |
auto_route(第三方) |
社区老牌路由方案,功能极强但略有学习曲线。 | 了解即可 ,如果团队已熟悉 go_router,无需切换。 |
go_router_sugar |
实验性项目,通过文件系统路由自动生成。 | 仅作视野拓展,尚未达到生产可用状态。 |