Files
App.K12.Student.Miniapp_Flu…/docs/demos/picker_page.md
T
2026-09-04 15:22:20 +08:00

3.9 KiB
Raw Blame History

【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 就够了,选择器页是最典型的"纯跳转 + 带值返回"场景。


五、踩坑记录

  1. pop 不带值 = 返回 null:用系统返回键关页时不会触发任何 pop(context, value),接收侧必须处理 null;
  2. 类型要配对:push<String> 对应 pop(context, '男');如果你 push 没写泛型,pop 的值类型就是 dynamic,接收侧要强转;
  3. pop 之后本页 context 已失效,别再 await 什么(本页没有异步,天然安全);
  4. 更多返回值的真实场景:日期选择、城市选择、筛选条件——结构都和本页一致。

六、扩展思考

  • 接收侧完整代码见 router_home_page.md(await push + context.mounted + ?? '未选择');
  • 参数传入的两种通道见 detail_page.md(构造参数 vs 命名路由 arguments);
  • 进阶:Navigator.pop 可以返回任意类型(对象、Map),比如"选了一个城市"返回整个城市模型,接收侧依然按泛型拿。