Dart中点击弹窗OK后关闭弹窗菜单并返回上页且触发POST请求的问题
解决方案:Flutter 弹窗与页面跳转的顺序问题
问题根源
- 连续调用3次
Navigator.pop(context)时,第三次跳转直接销毁了当前的QuestMenu组件,导致后续的API请求和刷新逻辑因组件已被释放而无法执行。 - 仅调用2次
pop时,虽然API请求正常执行,但缺少最后一次跳转回上一页的操作;而在onRefresh()后调用pop无效,是因为此时的context已不再指向原页面的导航栈。
修复步骤
1. 调整API请求与页面跳转的顺序
确保API请求和刷新逻辑在关闭弹窗/菜单后执行,再完成最后一次页面跳转。同时使用根导航器确保跳转操作能正确找到目标页面:
Expanded( child: PrimaryButton( label: 'OK', onPressed: () async { // 1. 关闭确认对话框 Navigator.pop(context); // 2. 关闭底部弹出菜单 Navigator.pop(context); // 3. 执行API请求(Riverpod Notifier独立于组件,即使组件被释放仍能正常运行) await ref .read(deactivateQuestNotifierProvider.notifier) .deactivateQuest(questId, token: token); // 4. 触发父页面刷新 onRefresh(); // 5. 使用根导航器跳转回上一页,避免context失效问题 Navigator.of(context, rootNavigator: true).pop(); }, ), ),
2. 完善useCallback的依赖项
原代码中useCallback的依赖项为空数组,会导致questId、token等变量无法被正确捕获,需补充依赖:
final onSubmit = useCallback( () async { // 原有弹窗逻辑 }, [questId, token, ref, onRefresh], // 添加所有用到的外部变量 );
3. 优化取消按钮的逻辑(可选)
通过showDialog的返回值统一处理菜单关闭,避免重复写pop:
// 取消按钮的onPressed onPressed: () { Navigator.pop(context, false); // 返回false标识取消操作 }, // 在onSubmit中处理返回结果 final confirmResult = await showDialog<bool>(...); if (confirmResult == false) { Navigator.pop(context); // 关闭底部菜单 }
为什么这样有效?
- 先关闭对话框和菜单,保证视觉上的交互流程符合预期;
- Riverpod的Notifier是全局状态管理对象,不受组件生命周期影响,因此即使
QuestMenu被释放,API请求仍能正常完成; - 使用
rootNavigator: true获取根导航器,确保最后一次跳转能正确定位到原页面的导航栈,避免因局部context失效导致跳转失败。
内容的提问来源于stack exchange,提问作者Chad Priddle
相关产品推荐
相关产品推荐

