文章目录
- 学习建议
- [基础层(6 题)](#基础层(6 题))
-
- [#1 `Navigator.push` 和 `pop` 做什么? 🔥](#1
Navigator.push和pop做什么? 🔥) - [#2 命名路由怎么用? ⭐](#2 命名路由怎么用? ⭐)
- [#3 `MaterialPageRoute` 是什么? 🔥](#3
MaterialPageRoute是什么? 🔥) - [#4 路由间如何传递参数与返回值? 🔥](#4 路由间如何传递参数与返回值? 🔥)
- [#5 如何拦截返回键? ⭐](#5 如何拦截返回键? ⭐)
- [#6 底部 Tab 导航常见结构? ⭐](#6 底部 Tab 导航常见结构? ⭐)
- [#1 `Navigator.push` 和 `pop` 做什么? 🔥](#1
- [进阶层(6 题)](#进阶层(6 题))
-
- [#7 Navigator 1.0 的局限? 🔥](#7 Navigator 1.0 的局限? 🔥)
- [#8 Navigator 2.0 核心组件? 🔥](#8 Navigator 2.0 核心组件? 🔥)
- [#9 `go_router` 解决什么问题? 🔥](#9
go_router解决什么问题? 🔥) - [#10 深链(Deep Link)如何处理? ⭐](#10 深链(Deep Link)如何处理? ⭐)
- [#11 嵌套导航与 `ShellRoute`? ⭐](#11 嵌套导航与
ShellRoute? ⭐) - [#12 路由与状态如何配合? ⭐](#12 路由与状态如何配合? ⭐)
- [核心层(6 题)](#核心层(6 题))
-
- [#13 Navigator 1.0 与 2.0 如何选型? 💡](#13 Navigator 1.0 与 2.0 如何选型? 💡)
- [#14 `RouterDelegate` 与状态驱动的关系? 💡](#14
RouterDelegate与状态驱动的关系? 💡) - [#15 Flutter 与 Android Activity 返回栈协同? 🔥](#15 Flutter 与 Android Activity 返回栈协同? 🔥)
- [#16 Web 与移动端路由差异? ⭐](#16 Web 与移动端路由差异? ⭐)
- [#17 路由鉴权与 redirect 模式? 🔥](#17 路由鉴权与 redirect 模式? 🔥)
- [#18 `Hero` 动画与路由? ⭐](#18
Hero动画与路由? ⭐) - 面试策略速查
- 完整链路一句通
- 相关推荐
学习建议
| 目标层级 | 建议 |
|---|---|
| 初级 | 掌握基础层 6 题:Navigator.push/pop、命名路由、MaterialPageRoute、路由传参、PopScope 拦截返回 |
| 中级 | 通读全文;进阶层能讲清 Navigator 2.0 页面栈、RouterDelegate、go_router 与深链、嵌套导航 |
| 高级 | 核心层必答:1.0 vs 2.0 选型与 tradeoff、混合栈与 Android Activity 协同、redirect 鉴权、Web 路由差异 |
基础层(6 题)
#1 Navigator.push 和 pop 做什么? 🔥
标准回答
Navigator 维护页面栈 (Route 列表)。push 压入新 Route 并播放过渡动画;pop 弹出栈顶返回上一页,可携带 result。pushReplacement 替换栈顶。根 Navigator 由 MaterialApp/CupertinoApp 自动提供。await Navigator.push(context, ...) 可异步接收返回结果,功能上类比 startActivityForResult。
面试官可能继续追问
-
Android
startActivity对照?push类似启动新 Activity;pop类似finish();result类似setResult。 -
多个 Navigator 嵌套?
子树可创建独立
Navigator,如底部 Tab 每 Tab 各自一套导航栈。
#2 命名路由怎么用? ⭐
标准回答
在 MaterialApp 的 routes 表中注册路径→页面映射,通过 Navigator.pushNamed(context, '/detail', arguments: id) 跳转。onGenerateRoute 用于处理动态路径与未知路由。简单应用够用,但复杂场景(深链、Web URL 同步、鉴权重定向)中,命令式命名路由表达能力不足,宜用 Navigator 2.0 或 go_router。
面试官可能继续追问
-
Android
intent-filter深链对照?命名路由不自动关联 URL;深链解析需 2.0 或
go_router配合。 -
arguments类型安全?运行时类型为
Object?,需手动强转;2.0 可用类型化的extra参数。
#3 MaterialPageRoute 是什么? 🔥
标准回答
实现 Android 风格左右滑入动画的 PageRoute 子类,builder 回调返回目标页 Widget。设置 fullscreenDialog: true 可变为自下而上弹出。自定义过渡效果用 PageRouteBuilder。Route 对象本身负责遮罩、动画、手势返回等行为,页面 Widget 在 build 中按需构建。
面试官可能继续追问
-
Android 共享元素过渡?
用
Hero组件声明同名 tag 即可实现跨路由飞行动画;复杂共享可用第三方库。 -
透明路由?
自定义
PageRoute,设置barrierColor: Colors.transparent等属性。
#4 路由间如何传递参数与返回值? 🔥
标准回答
去程传参 :构造函数直接传、ModalRoute.settings.arguments、或 Navigator 2.0 的 state.extra。回程返回值 :Navigator.pop(context, result) 弹出,上一页通过 final r = await Navigator.push(...) 接收。复杂对象建议传 id 再由状态管理容器查询,避免在路由中传递大对象。深链接参数则通过 query/path 解析。
面试官可能继续追问
-
Android Bundle 对照?
arguments类似 Bundle;Flutter 无 Parcelable 机制,常用 JSON 或 id 传递。 -
pop 多次怎么处理?
用
popUntil或pushNamedAndRemoveUntil清空中间栈,常用于跳转到登录页。
#5 如何拦截返回键? ⭐
标准回答
Flutter 3.12+ 使用 PopScope(替代已废弃的 WillPopScope):canPop 控制是否允许系统返回;onPopInvoked 回调处理侧滑或返回键事件,即使 canPop: false 也会触发。典型场景:表单未保存弹确认对话框、支付流程中禁止返回。Android 预测性返回手势需配合 PopScope 与主题设置。
面试官可能继续追问
-
Android
OnBackPressedDispatcher对照?拦截机制类似;混合页面中原生与 Flutter 可能争抢返回事件,需约定消费优先级。
-
canPop: false后怎么退出?业务条件满足后手动调用
Navigator.pop,或通过 Channel 通知原生finish()。
#6 底部 Tab 导航常见结构? ⭐
标准回答
常见方案:Scaffold + BottomNavigationBar + 每个 Tab 一个子 Navigator,配合 IndexedStack 保持各 Tab 页面状态。go_router 则用 StatefulShellRoute 为每个分支维护独立导航栈。切换 Tab 时不丢失滚动位置,需搭配 AutomaticKeepAliveClientMixin。切忌全应用单栈导致 Tab 间路由互相干扰。
面试官可能继续追问
-
Android
BottomNavigationView+ 多 Fragment 对照?每 Tab 独立 back stack,Flutter 对应嵌套
Navigator或 shell route。 -
Tab 内再 push 详情页?
在对应 Tab 的子
Navigator内 push,不影响其他 Tab 的导航栈。
进阶层(6 题)
#7 Navigator 1.0 的局限? 🔥
标准回答
命令式 push/pop API 使路由状态隐式 存在于内部栈中,难以与 URL 栏、系统返回手势、状态恢复保持同步。深链解析、Web 同构、登录重定向等场景需大量样板代码。路由状态不可序列化,调试与测试困难。因此官方推出 Navigator 2.0 声明式模型:pages 列表即真相源,系统事件通过改变 pages 驱动栈重建。
面试官可能继续追问
-
Android 单 Activity 多 Fragment 像 2.0 吗?
思想相近:回退栈由状态驱动而非命令式操作;Flutter 2.0 用
pages显式声明。 -
小项目还要 2.0 吗?
可继续用 1.0;若要 Web 或深链支持,直接用
go_router封装更省事。
#8 Navigator 2.0 核心组件? 🔥
标准回答
RouteInformationParser :URI 与 RouteInformation 互转。RouterDelegate :持有 Navigator 的 pages 列表,监听状态变化并通过 notifyListeners 触发重建。RouteInformationProvider :提供当前路由信息(含平台深链事件)。三者通过 MaterialApp.router 接入。与 1.0 的关键区别:页面列表变化驱动栈,而非直接调用 push/pop。
面试官可能继续追问
-
手写难度大吗?
样板代码多;生产环境推荐用
go_router或auto_route自动生成。 -
pages和 1.0 的routes关系?2.0 用
Page对象列表(如MaterialPage)替代 1.0 隐式栈,状态即文档。
#9 go_router 解决什么问题? 🔥
标准回答
官方维护的声明式路由 库,提供路径模板、query 参数、redirect 重定向、ShellRoute 嵌套、深链支持、Web URL 同步。通过 GoRouter(routes: [...], redirect: ...) 配置,UI 层用 context.go/context.push 导航。大幅降低手写 Navigator 2.0 RouterDelegate 的成本,是近 1 年新项目的高频选型。
面试官可能继续追问
-
Android
Navigation Component对照?类似 nav graph + deep link 配置;
go类似navigate加popUpTo。 -
未登录跳转登录页?
redirect: (context, state) => isLoggedIn ? null : '/login'统一拦截。
#10 深链(Deep Link)如何处理? ⭐
标准回答
移动端:通过 uni_links 或 app_links 接收 URI,交给 GoRouter 或自定义 parser 解析,匹配对应 route,可能先经过 redirect 拦截。Android 端需在 AndroidManifest.xml 配置 intent-filter。冷启动与热启动都需处理;参数校验防止非法 path。生产环境推荐 HTTPS App Links 并验证域名所有权。
面试官可能继续追问
-
Android
intent.data怎么进 Flutter?FlutterActivity设置初始 route,或通过 MethodChannel 传递 URI 给go_router.go。 -
http/https 与自定义 scheme 选择?
生产推荐 HTTPS App Links 验证域名;开发调试可用自定义 scheme。
#11 嵌套导航与 ShellRoute? ⭐
标准回答
go_router 的 ShellRoute / StatefulShellRoute 为页面包裹共享外壳(底栏、侧栏),子路由在壳内切换且各自保持独立导航栈 ,对应多 Tab 场景每 Tab 可有多层详情。通过 parentNavigatorKey 可将特定路由(如全屏登录页)挂载到根 Navigator,覆盖外壳。
面试官可能继续追问
-
主界面 + 全屏登录页布局?
登录 route 使用根
navigatorKey,不进入 Shell 分支。 -
Tab 切换保留各自栈?
StatefulShellRoute.indexedStack保持各分支页面状态不丢失。
#12 路由与状态如何配合? ⭐
标准回答
路由参数尽量可序列化 (如 id),详情页通过 Provider/Riverpod 按 id 获取数据,而非在路由中传递完整对象。勿在 RouteSettings 中塞入 BuildContext 或大对象导致泄漏。登录态变化触发 redirect 清空非法页面栈。返回结果用 pop(result),上一页通过 await push 接收后刷新对应 provider,避免全局广播。
面试官可能继续追问
-
返回后如何刷新列表?
await push收到 result 后调用ref.invalidate(listProvider)触发重新请求。 -
路由级状态恢复?
使用
RestorationMixin或restorationId配合系统状态恢复 API。
核心层(6 题)
#13 Navigator 1.0 与 2.0 如何选型? 💡
标准回答
1.0 :页面少、无 Web 需求、团队熟悉命令式 API。2.0 / go_router :需深链、Web 同构、复杂 redirect 鉴权、可预测回退栈。渐进迁移可让新模块用 go_router,旧模块 1.0 共存于不同 Navigator。面试时应讲清各自 tradeoff,而非简单否定 1.0。
面试官可能继续追问
-
存量 Activity 路由如何共存?
原生层仍用 Activity,Flutter 模块内独立
GoRouter,边界通过 Channel 协调跳转。 -
学习成本如何评估?
2.0 概念较多(Parser、Delegate);
go_router通过声明式路由表大幅降低入门门槛。
#14 RouterDelegate 与状态驱动的关系? 💡
标准回答
RouterDelegate 继承 ChangeNotifier,内部 pages 列表变化时调用 notifyListeners,触发 MaterialApp.router 重建 Navigator。系统返回键由 popRoute 回调修改 pages。核心思想是声明式 :状态 → pages → UI,而非 UI 层直接命令式操作隐式栈。测试时可直接验证 delegate 的 pages 序列。
面试官可能继续追问
-
背压到根路由怎么退出?
pages清空后无法再 pop,通过SystemNavigator.pop()或 Channel 通知原生finish()。 -
多处修改 pages 会冲突吗?
应集中到单一
RouterDelegate管理,避免分散setState导致竞态。
#15 Flutter 与 Android Activity 返回栈协同? 🔥
标准回答
混合应用常见形态:单 Activity 承载全量 Flutter 或 多 Activity 各自嵌入 FlutterFragment 。Flutter 内 pop 到根后继续退出的行为,需通过 SystemNavigator.pop() 或 MethodChannel 通知原生层 finish()。Android 预测性返回手势、多 Fragment 回退场景需明确约定:Flutter 先消费返回事件还是原生先消费。FlutterEngine 缓存时路由状态保留在 Dart 侧。
面试官可能继续追问
-
Flutter 页上再启动原生 Activity?
Channel 调用
startActivity,返回后 FlutterRoute仍在引擎栈中未销毁。 -
双返回键体验不一致?
在根路由的
PopScope中统一判断,无法继续 pop 时通知原生执行finish()。
#16 Web 与移动端路由差异? ⭐
标准回答
Web 端强依赖地址栏 URL 与浏览器前进后退按钮;go_router 通过 path 或 hash 策略管理 URL。移动端深链无地址栏,但推荐与 Web 端共用相同 path 设计便于同构。Web 需注意:刷新页面时入口 route 必须能独立渲染当前状态。使用 url_strategy 去除 URL 中 # 符号需要服务端配合重写。
面试官可能继续追问
-
只做 App 不考虑 Web?
仍建议用
go_router统一 path 规范,后续扩展 Web 成本更低。 -
SEO 与 Flutter Web 的关系?
Android 面试点到即可;首屏渲染模式选择影响 SEO 策略,但非核心考点。
#17 路由鉴权与 redirect 模式? 🔥
标准回答
GoRouter.redirect 在每次导航前检查登录态或权限,未授权时返回登录页路径,并可携带 returnTo query 参数以便登录后回跳。异步读取 token 时注意避免 redirect 重入死循环与闪屏,可用 loading 壳路由承载过渡态。角色级权限用 guard 函数或分支 redirect 实现。关键 :避免在 Widget build 中调用 context.go 造成循环重建。
面试官可能继续追问
-
原生登录态 Flutter 未感知?
Channel 通知刷新
authStateProvider,触发refreshListenable使GoRouter重跑 redirect。 -
token 过期如何踢出?
网络 401 拦截后调用
context.go('/login')并清空导航栈,等价于pushReplacement。
#18 Hero 动画与路由? ⭐
标准回答
两路由间同名 Hero tag 的 Widget 在 push/pop 时自动生成飞行动画。tag 必须全局唯一;列表项用唯一 id 作为 tag。嵌套 Hero 或过多 Hero 同时飞行会引发性能问题。与 MaterialPageRoute 默认过渡动画可叠加展示。复杂共享元素场景可自定义 flightShuttleBuilder 控制飞行过程。
面试官可能继续追问
-
Android 共享元素 Transition 对照?
设计思想一致;Flutter 声明 tag 即可自动过渡,但要求两端 Widget 子树结构匹配。
-
Hero 报错常见原因?
tag 重复、子树缺少 Material 祖先、列表项未使用唯一 tag 标识。

面试策略速查
| 面试等级 | 建议掌握 |
|---|---|
| 初级 | ★★★☆☆ |
| 中级 | ★★★★☆ |
| 高级 | ★★★★★ |
必背知识(🔥)
push/pop 与结果回传、命名路由与 onGenerateRoute、Navigator 1.0 局限、2.0 三组件、go_router 声明式配置、深链接入处理、混合返回栈协同、redirect 鉴权模式
高频追问
「1.0 和 2.0 区别及选型」「go_router redirect 怎么写」「Tab 怎么保持各自导航栈」「Flutter 根路由如何 finish Activity」「Hero 常见坑」
加分项(💡)
RouterDelegate 状态驱动原理、ShellRoute 嵌套导航、Web 路由差异与同构、1.0→2.0 渐进迁移策略
容易踩坑
混用多套 Navigator 未指定 key;redirect 条件不当导致死循环;深链冷启动未处理参数;混合栈根路由未调用 SystemNavigator.pop;arguments 强转类型崩溃;build 中调用 go 引发循环重建
完整链路一句通
路由导航一条线 :URI 输入或用户操作 → Parser 解析 / redirect 鉴权拦截 → 更新路由状态 → pages 列表驱动 Navigator 重建栈 → 页面通过状态容器按参数取数据 → pop(result) 回传上一页;混合栈根路由无路可退时通知原生 finish()。