Flutter如何防止异步函数内Navigator.pop()弹出已不存在路由
Flutter加载弹窗误pop路由解决方案
你遇到的问题本质是异步操作时序和路由状态不匹配:网络请求完成时机和用户手动关闭弹窗的时机并行,代码未校验弹窗存活状态就执行pop,自然会误退下层页面。不需要用WillPopScope硬拦截返回键,用轻量状态标记就能实现需求,同时完整保留用户耗时过长时主动中止流程的能力。
实现步骤
- 新增布尔类型标记位,专门记录加载弹窗的活跃状态
- 监听
showDialog返回的Future:这个Future会在弹窗被关闭时触发完成,触发源覆盖所有弹窗关闭场景——用户按返回键、点击弹窗蒙层、代码主动调用pop,只要Future完成就把弹窗活跃标记设为false - 网络请求执行完成后,先校验弹窗活跃标记,同时确认当前页面上下文还处于挂载状态,两个条件都满足时再执行pop关闭弹窗,否则直接跳过pop逻辑
注意:不要用
Navigator.canPop(context)做判断,这个方法仅校验当前导航栈是否存在可pop的路由。用户提前关掉弹窗后,下层页面本身处于可pop状态,此时canPop会返回true,执行pop依然会误退页面。
修正后的可运行代码
ElevatedButton( onPressed: () async { bool isDialogShowing = false; // 弹出加载弹窗 showDialog( context: context, barrierDismissible: false, // 按需配置:设为true时允许用户点击弹窗蒙层主动关闭 builder: (_) => const Center(child: CircularProgressIndicator()), ).then((_) { // 弹窗被任意方式关闭时,更新标记位 isDialogShowing = false; }); isDialogShowing = true; // 执行异步网络请求,需要支持取消请求的话可以搭配网络库的取消令牌实现 await asyncNetworkOperation(); // 仅当弹窗仍在展示、当前页面未销毁时,才执行关闭弹窗的操作 if (isDialogShowing && context.mounted) { isDialogShowing = false; Navigator.pop(context); } }, child: const Text("Press here"), )
可选扩展
如果你希望用户主动关闭弹窗时同步取消还在执行的网络请求,避免无意义的资源消耗,可以在showDialog的then回调中触发网络请求的取消逻辑,不需要额外编写其他拦截代码。
内容的提问来源于stack exchange,提问作者Michele
相关产品推荐
相关产品推荐

