Navigator 1.0 核心:Navigator和Route的关系、push和pop操作、路由栈的工作原理
好,咱们今天来聊聊 Navigator 1.0。说实话,虽然现在 2.0 甚至 GoRouter 都出来了,但 1.0 这套东西,你无论如何都得吃透。为什么?因为它是 Flutter 路由的「地基」。你想想看,2.0 再怎么封装,底层还是离不开 Navigator 和 Route 这套机制。
我个人习惯,在接手一个新项目时,第一件事就是看它的路由是怎么组织的。如果连 push 和 pop 都写得乱七八糟,那这个项目的代码质量,基本可以打个问号了。
Navigator 和 Route:一对老搭档
先搞清楚这两个家伙的关系。说白了,Navigator 是管家,Route 是页面。
- Navigator:负责管理一个栈结构,它知道当前栈顶是哪个 Route,也知道怎么把新的 Route 放上去,或者把旧的 Route 拿下来。
- Route:代表一个「页面」或者「视图」。它不关心自己是怎么被推上来的,也不关心什么时候被移除,这些事全交给 Navigator 去操心。
我在项目中遇到过一种情况:有人试图在 Route 里面直接操作 Navigator 的栈,结果搞得一团糟。记住,Route 只负责「展示什么」,Navigator 才负责「怎么切换」。各司其职,代码才清爽。
核心原则:Navigator 是路由栈的管理者,Route 是栈中的元素。你永远不要直接操作栈的内部结构,而是通过 Navigator 提供的 push、pop 等 API 来间接操作。
push 和 pop:入栈与出栈
这两个操作,是路由栈最核心的动作。咱们直接看代码:
// 入栈操作:将新路由推入栈顶
Navigator.push(
context,
MaterialPageRoute(builder: (context) => SecondPage()),
);
// 出栈操作:移除栈顶路由
Navigator.pop(context);
嗯,这里要注意一个细节。push 的时候,你需要提供一个 Route 对象。MaterialPageRoute 是 Flutter 内置的一个 Route 实现,它帮你处理了页面切换动画、路由名称等琐事。你当然也可以自己写一个 Route 子类,但说实话,大部分场景下 MaterialPageRoute 够用了。
我曾经踩过一个坑:在 push 的时候忘了传 context,结果 Navigator 找不到当前的路由栈,直接报错。你想想看,一个页面跳转都做不了,用户会怎么想?所以,context 一定要是当前页面 Widget 树中的 context,别乱传。
小技巧:如果你需要在 push 之后等待返回结果,可以这样写:
final result = await Navigator.push(
context,
MaterialPageRoute(builder: (context) => SecondPage()),
);
// 当 SecondPage 调用 Navigator.pop(context, 'someData') 时,
// result 就会接收到 'someData'
这个模式在表单填写、选择器等场景下非常实用。
路由栈的工作原理:后进先出
路由栈,本质上就是一个「后进先出」的数据结构。你每次 push,新页面就压在栈顶;你每次 pop,栈顶页面就被移除,露出下面的页面。
咱们用一个例子来说明:
- 初始状态:栈里只有 HomePage(栈底)
- push SecondPage:栈变成 [HomePage, SecondPage](SecondPage 在栈顶)
- push ThirdPage:栈变成 [HomePage, SecondPage, ThirdPage](ThirdPage 在栈顶)
- pop:移除 ThirdPage,栈变回 [HomePage, SecondPage](SecondPage 重新成为栈顶)
- pop:移除 SecondPage,栈变回 [HomePage](HomePage 重新成为栈顶)
为什么会这样?因为 Flutter 的页面切换,本质上就是栈的压入和弹出。你想想看,当你从首页跳到详情页,再跳到编辑页,然后一步步返回,是不是就是这个过程?
我在项目中遇到过一种情况:用户连续快速点击按钮,导致多次 push 同一个页面。结果栈里出现了好几个相同的页面,返回的时候要按好几次才能回到首页。这就是典型的「栈污染」。解决方案也很简单:在 push 之前,判断一下当前栈顶是不是目标页面,如果是,就别再 push 了。
避坑指南:我曾经在做一个电商项目时,因为路由栈管理不当,导致用户在支付页面按返回键时,直接跳回了首页,而不是回到订单确认页。后来我加了一个「路由拦截器」,在 pop 之前检查当前栈的状态,确保返回行为符合用户预期。
记住:路由栈的深度和顺序,直接决定了用户的导航体验。别让用户迷路。
总结一下
Navigator 1.0 的核心,说白了就三件事:
- Navigator 是管家,负责管理路由栈
- Route 是页面,负责展示内容
- push 和 pop 是入栈和出栈的操作,遵循后进先出原则
你把这些搞清楚了,Navigator 1.0 就算入门了。下一章,咱们聊聊更高级的用法——命名路由和路由传参。嗯,那才是真正考验架构能力的地方。