Flutter中Navigator.pop重复点击致黑屏问题及优化方案咨询
解决Flutter登录功能的重复弹窗/黑屏及BuildContext异步使用问题
问题根源
- 频繁点击登录按钮会多次触发
showDialog,后续多次执行pop会超出栈中对话框的数量,导致黑屏。 - 异步操作中直接使用
BuildContext,若组件在异步任务完成前已销毁,会引发错误,VS的提示正是针对此风险。
优化方案
1. 按钮防重复点击控制
添加布尔变量标记登录状态,点击后立即禁用按钮,避免重复触发请求。
2. 精准管理对话框生命周期
通过存储加载框的BuildContext,确保只关闭当前弹出的加载弹窗,避免误操作栈中其他页面/对话框。
3. 异步操作前检查组件挂载状态
使用mounted属性判断组件是否仍处于活跃状态,避免在组件销毁后使用context引发错误。
修改后的完整代码
bool _isLoading = false; void signUserIn() async { if (_isLoading) return; // 拦截重复点击 _isLoading = true; // 存储当前加载框的context,用于精准关闭 late BuildContext dialogContext; await showDialog( context: context, barrierDismissible: false, // 禁止点击空白关闭加载框 builder: (context) { dialogContext = context; return const Center( child: CircularProgressIndicator(), ); }, ); try { await FirebaseAuth.instance.signInWithEmailAndPassword( email: emailController.text, password: passwordController.text, ); } on FirebaseException catch (e) { // 组件仍挂载时才弹出错误提示 if (!mounted) return; if (e.code == 'user-not-found') { wrongEmailMessage(); } else if (e.code == 'wrong-password') { wrongPasswordMessage(); } } finally { // 无论成功失败,都恢复按钮状态并关闭加载框 if (mounted) { Navigator.of(dialogContext).pop(); _isLoading = false; } } } void wrongEmailMessage() { showDialog( context: context, builder: (context) { return const AlertDialog( title: Text('邮箱错误'), ); }, ); } void wrongPasswordMessage() { showDialog( context: context, builder: (context) { return const AlertDialog( title: Text('密码错误'), ); }, ); }
关键优化点说明
_isLoading变量:从源头阻止重复点击触发登录流程。barrierDismissible: false:避免用户误操作关闭加载框,保证登录流程的完整性。dialogContext:精准定位当前加载框,避免多弹窗场景下的误关闭操作。finally块:统一处理加载框关闭和按钮状态恢复,逻辑更简洁可靠。mounted检查:彻底解决异步操作中使用BuildContext的风险,消除VS的警告提示。
内容的提问来源于stack exchange,提问作者RogarTK
相关产品推荐
相关产品推荐

