You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何从DropdownMenuItem的onTap调用Navigator.push()并等待返回值?

解决DropdownMenuItem异步跳转路由导致的类型转换异常

我通过Provider从数据库动态填充DropdownFormField,需要添加一个DropdownMenuItem:选中该选项时跳转到新路由插入数据库记录,返回时把新插入记录的ID设为下拉框的选中值。尝试了两种方案,遇到了类型转换异常问题:

方案一:TextButton作为子组件

  • 效果:跳转和返回逻辑正常,返回后下拉框选中值能正确更新,但样式和普通菜单项不一致,点击按钮不会自动关闭下拉菜单,需点击外部才会收起。
  • 代码示例:
DropdownMenuItem<int>(
  child: TextButton(
    onPressed: () async {
      final int newValue = await Navigator.push(context, AddNewTeaProducerRoute());
      setState(() {
        _selectedValue = newValue;
      });
    },
    child: Text('Add New Manufacturer')
  )
);

方案二:Text作为子组件(触发异常)

  • 问题:在DropdownMenuItem的onTap中写异步跳转逻辑,会直接抛出异常Unhandled Exception: type '_DropdownRouteResult<int>' is not a subtype of type 'int?'。调试发现,newValue会被立即赋值为Future/_DropdownRouteResult<int>,而非等待路由返回的int类型。
  • 代码示例:
DropdownMenuItem<int>(
  onTap: () async {
    final int newValue = await Navigator.push(context, AddNewTeaProducerRoute());
    setState(() {
      _selectedValue = newValue;
    });
  },
  child: const Text('Add New Manufacturer')
);

原因分析

DropdownMenuItem的onTap并非为异步操作设计:点击该选项时,下拉路由(DropdownRoute)会自动尝试将当前item的value返回给DropdownFormField。而我们的异步Navigator.push还未完成,此时下拉路由返回的_DropdownRouteResult<int>类型,和DropdownFormField期望的int?类型不匹配,从而触发类型转换异常。而TextButton的onPressed不会触发DropdownMenuItem的默认选中逻辑,因此不会产生冲突。

可行解决办法

方法1:设置空value并手动关闭下拉菜单

将DropdownMenuItem的value设为null,避免下拉路由返回无效值;在onTap中先关闭下拉菜单,再执行跳转逻辑:

DropdownMenuItem<int>(
  value: null,
  onTap: () async {
    // 先关闭下拉菜单
    Navigator.pop(context);
    // 跳转路由并等待返回ID
    final int? newValue = await Navigator.push(context, AddNewTeaProducerRoute());
    if (newValue != null) {
      setState(() {
        _selectedValue = newValue;
      });
    }
  },
  child: const Text('Add New Manufacturer')
);

方法2:用InkWell包裹子组件保留样式

禁用DropdownMenuItem的默认点击逻辑,用InkWell包裹子元素处理点击,既保留菜单项的原生样式,又能正常执行异步操作:

DropdownMenuItem<int>(
  enabled: false,
  child: InkWell(
    onTap: () async {
      Navigator.pop(context);
      final int? newValue = await Navigator.push(context, AddNewTeaProducerRoute());
      if (newValue != null) {
        setState(() {
          _selectedValue = newValue;
        });
      }
    },
    child: const Text('Add New Manufacturer'),
  ),
);

内容的提问来源于stack exchange,提问作者A Dunn

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.23 12:15:28