3.9 KiB
3.9 KiB
【Demo】选择器页:pop 带值返回
源文件:
lib/pages/demo/picker_page.dart| 分类:路由 一句话:路由返回值的经典用法 —— 点"男/女",把结果带回上一个页面。
一、这个 Demo 解决什么问题
"选性别"这类选择器页:打开 → 点选项 → 关闭并把结果带回调用页。 本页是 34 行的最小完整例子,专门讲清 pop 的第二个参数。
首页 await push 选择器页 → 用户点"男" → Navigator.pop(context, '男')
→ 首页的 await 拿到 '男' → 弹 SnackBar 展示
对照 Vue:等价于
this.$emit('select', '男')后关闭弹窗——Flutter 里返回值走pop的第二个参数。
二、怎么运行 / 演示内容
runApp(const RouterApp()); // 从首页"方式 2"按钮进入本页
首页点"选择性别" → 本页两个选项(男/女)→ 点任一 → 回到首页并弹 SnackBar 显示结果; 按系统返回键(不选)→ 首页提示"未选择"。
三、核心知识点(新手向)
1. pop 的第二个参数就是"返回值"
ListTile(
title: const Text('男'),
onTap: () => Navigator.pop(context, '男'), // 第二个参数:返回给上一页的值
),
2. 与 push 侧配对使用
// 接收侧(router_home_page.dart)
final result = await Navigator.push<String>(context, MaterialPageRoute(...));
// 返回侧(本页)
Navigator.pop(context, '男');
pop(context, value)的值类型与push<String>的泛型对应;- 用户没选(系统返回键 / 手势返回)→ 没调 pop 带值 → 接收侧拿到
null,所以接收侧要?? '未选择'兜底。
3. pop 之后,页面就销毁了
Navigator.pop 会把当前路由出栈并销毁。所以pop 之后再不能用本页的 context(页面没了)——这也是"await 之后判 mounted"问题的另一面。
四、关键代码剖析
class PickerPage extends StatelessWidget {
const PickerPage({super.key});
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(title: const Text('选择性别')),
body: Column(
children: [
ListTile(
leading: const Icon(Icons.male, color: Color(0xFF3B82F6)),
title: const Text('男'),
trailing: const Icon(Icons.chevron_right),
onTap: () => Navigator.pop(context, '男'), // ← 带值返回
),
Divider(height: 1.h, indent: 16, endIndent: 16),
ListTile(
leading: const Icon(Icons.female, color: Color(0xFFF06292)),
title: const Text('女'),
trailing: const Icon(Icons.chevron_right),
onTap: () => Navigator.pop(context, '女'),
),
],
),
);
}
}
全程没有 setState、没有返回值声明——StatelessWidget 就够了,选择器页是最典型的"纯跳转 + 带值返回"场景。
五、踩坑记录
- pop 不带值 = 返回 null:用系统返回键关页时不会触发任何
pop(context, value),接收侧必须处理 null; - 类型要配对:
push<String>对应pop(context, '男');如果你 push 没写泛型,pop 的值类型就是 dynamic,接收侧要强转; - pop 之后本页 context 已失效,别再 await 什么(本页没有异步,天然安全);
- 更多返回值的真实场景:日期选择、城市选择、筛选条件——结构都和本页一致。
六、扩展思考
- 接收侧完整代码见 router_home_page.md(
await push+context.mounted+?? '未选择'); - 参数传入的两种通道见 detail_page.md(构造参数 vs 命名路由 arguments);
- 进阶:
Navigator.pop可以返回任意类型(对象、Map),比如"选了一个城市"返回整个城市模型,接收侧依然按泛型拿。