路由与页面组织:从小项目到复杂业务
Flutter 实战系列第 5 篇。
目标:让页面跳转、参数传递、页面拆分在中大型项目里可维护。
1. 问题背景:业务场景 + 现象
小项目里直接 Navigator.push 没问题,但业务变复杂后会出现:
- 路由字符串散落各处,拼写错误难发现
- 参数通过
dynamic传递,运行时才报错 - 页面职责失控:一个页面 1000+ 行
- 返回逻辑、深链跳转、统一拦截难维护
- 新人很难快速定位“从哪跳到哪”
2. 原因分析:核心原理 + 排查过程
2.1 核心原理
路由不是“页面跳转 API”,而是“应用导航协议”:
- 页面入口要可枚举
- 参数结构要类型化
- 跳转动作要可拦截(登录态、埋点、灰度)
- 页面组织要遵循“容器页 + 业务组件”拆分
2.2 常见反模式
- 全局到处写
Navigator.of(context).push(...) - 路由名硬编码字符串
- 参数不建模,直接
Map或dynamic - 页面同时承担 UI、网络、业务流程
- 回调地狱和多层嵌套导航难排查
3. 解决方案:方案对比 + 最终选择
3.1 方案对比
-
分散式路由(各写各的)
上手快,但复杂后治理困难 -
集中式路由注册 + 类型化参数(推荐)
初期成本稍高,长期收益明显
3.2 最终选择
- 路由定义集中管理(枚举/常量)
- 参数统一建模(RouteArgs)
- 跳转统一通过 NavigatorService(便于拦截)
- 页面按“Page(容器) + Section/Widget(表现) + ViewModel(逻辑)”拆分
4. 关键代码:最小必要代码片段
4.1 路由常量与参数模型
abstract class AppRoutes {
static const room = '/room';
static const wallet = '/wallet';
static const userProfile = '/user/profile';
}
class RoomRouteArgs {
final String roomId;
final bool autoJoinAudio;
const RoomRouteArgs({required this.roomId, this.autoJoinAudio = false});
}