Flutter中如何正确接收showBottomSheet返回的回传数据
showBottomSheet接收回传数据实现方案
问题现象
开发中使用showModalBottomSheet时,可在弹窗内通过Navigator.pop(context, data)回传数据,在调用处链式调用then方法即可接收返回值,参考实现如下:
showModalBottomSheet( context: context, builder: (BuildContext context) { return Padding( padding: EdgeInsets.fromLTRB(0, AppBar().preferredSize.height, 0, 0), child: CountryPicker( countryCodes: countryCodes, ), ); }, ).then((value) { setState(() { countryCodeIndex = value; }); });
但相同写法套用到showBottomSheet上时,调用then方法会直接抛出如下错误:
The method 'then' isn't defined for the type 'PersistentBottomSheetController'. Try correcting the name to the name of an existing method, or defining a method named 'then'
报错原因是showBottomSheet的返回值类型为PersistentBottomSheetController,该类型本身没有定义then方法,无法直接像模态底部弹窗一样链式接参。
解决方法
方法1:通过控制器的closed属性接收返回值
PersistentBottomSheetController暴露了closed属性,本质是一个Future对象,会在底部弹窗关闭时complete,携带的结果就是Navigator.pop传入的回传参数,实现代码如下:
// 先拿到showBottomSheet返回的控制器实例 final sheetController = showBottomSheet( context: context, builder: (BuildContext context) { return Padding( padding: EdgeInsets.fromLTRB(0, AppBar().preferredSize.height, 0, 0), child: CountryPicker( countryCodes: countryCodes, ), ); }, ); // 监听closed Future拿返回值 sheetController.closed.then((value) { // 加判空兼容手动滑关弹窗无传参的场景 if (value != null) { setState(() { countryCodeIndex = value; }); } });
弹窗内的传参逻辑和showModalBottomSheet完全一致,选中目标项时执行Navigator.pop(context, 选中下标)即可把参数回传。
方法2:通过组件回调直接传值
如果不想依赖路由传参逻辑,可以直接给弹窗内的组件传入选择回调,选中时直接触发更新,不需要等路由返回:
showBottomSheet( context: context, builder: (BuildContext context) { return Padding( padding: EdgeInsets.fromLTRB(0, AppBar().preferredSize.height, 0, 0), child: CountryPicker( countryCodes: countryCodes, // 传入选中回调 onCountrySelect: (selectIndex) { // 直接更新状态 setState(() { countryCodeIndex = selectIndex; }); // 关闭弹窗,不需要传参 Navigator.pop(context); }, ), ); }, );
这种写法逻辑更直观,不会受路由返回机制影响,复杂业务场景下维护成本更低。
注:如果是用户手动滑动关闭
showBottomSheet,closed返回的value为null,业务代码里记得做空值判断,避免空指针异常。
内容的提问来源于stack exchange,提问作者GDTyka
相关产品推荐
相关产品推荐

