递归调用中先关闭BottomSheet后如何重新打开它?
问题解决:点击Try Again后新BottomSheet不显示的问题
你的问题出在BottomSheet内部上下文使用不当,以及未等待Navigator.pop完成就执行递归调用。以下是具体修复方案:
核心问题分析
Navigator.of(context).pop()是异步操作,直接在其后调用handleBuyerCall,可能在弹窗未完全关闭时就触发新弹窗,导致上下文冲突。- 你在
CustomBottomSheet的onPressed中使用的是BottomSheet内部的context,递归调用时传递该上下文会导致新弹窗无法正确挂载——因为这个上下文已属于被关闭的BottomSheet。
修复后的代码
Future<void> handleBuyerCall( BuildContext context, Kms kms, NumberMasking numberMasking, ) async { if (kms.Value != "") { final phone = await numberMasking.getNumberMasking(kms.Value!); if (phone != null) { await showModalBottomSheet( context: context, builder: (BuildContext context) => CustomBottomSheet( onPressed: () { launchCall(phone); }, imgUrl: "assets/images/green_tick.svg", heading: "Connection Established", subHeading: "Please click on the below option to place a call to the buyer", text: "Call Buyer", twoCta: false, ), ); } else { if (context.mounted) { await showModalBottomSheet( context: context, // 将BottomSheet内部上下文重命名,与原始上下文区分 builder: (BuildContext sheetContext) => CustomBottomSheet( onPressed: () async { // 等待弹窗关闭完成 await Navigator.of(sheetContext).pop(); // 传递原始上下文,而非BottomSheet内部上下文 handleBuyerCall(context, kms, numberMasking); }, imgUrl: "assets/images/cross.svg", heading: "Failed to Connect", subHeading: "Please click on the below option to place a call to the buyer", text: "Try Again", text1: "Back", twoCta: true, ), ); } } } }
关键改动点
- 上下文区分:将builder中的context重命名为
sheetContext,明确区分页面原始上下文和BottomSheet内部上下文。 - 等待异步完成:用
await等待Navigator.pop执行完毕,确保弹窗完全关闭后再触发递归。 - 传递正确上下文:递归调用时使用页面原始
context,保证新弹窗能正确挂载到页面导航栈中。
额外优化提示
如果之前加延迟能临时解决问题,本质是规避了异步顺序冲突,但上述修复是根本解决方法。若需求允许,可给showModalBottomSheet添加isDismissible: false,避免用户误触关闭弹窗导致逻辑混乱。
内容的提问来源于stack exchange,提问作者lakhera24
相关产品推荐
相关产品推荐

