Flutter实现showSnackBar遇报错:Don't use 'BuildContext's across async gaps
解决Flutter中"Don't use 'BuildContext's across async gaps"错误
这个报错的核心原因是:你在异步操作(比如await http.post)完成后直接使用了BuildContext。异步等待的过程中,当前Widget可能已经被销毁(比如用户返回上一页),此时context已经失效,继续调用会引发异常。
最简单的修复方案:添加mounted检查
在调用ScaffoldMessenger.of(context)之前,先判断当前Widget是否还处于挂载状态(mounted为true),确保context有效后再执行弹窗逻辑。
修改后的代码如下:
//Post reply replyThread() async{ setState(() { _isSubmitted = true; }); try{ var res = await http.post( Uri.parse(API.quickThreadReplyURL), body: { 'post_id': _postid.toString(), 'userID': userID.toString(), 'sessionData': sessionData.toString(), 'content': contentController.text, }, ); if(res.statusCode==200){ //Clear textfield contentController.text = ''; final resBody = jsonDecode(res.body); bool success = resBody['success']; if(success){ List thread = resBody['threadList'] as List; setState(() { threadReplies = thread + threadReplies; _isSubmitted = false; }); //Show toaster if(mounted){ // 新增mounted检查 ScaffoldMessenger.of(context).showSnackBar( const SnackBar( backgroundColor: Color.fromARGB(255, 139, 247, 92), content: Text( "New thread reply successfully posted", style: TextStyle(color: Colors.black), ), ) ); } } else{ setState(() { _isSubmitted = false; }); //Show toaster if(mounted){ // 新增mounted检查 ScaffoldMessenger.of(context).showSnackBar( const SnackBar( backgroundColor: Color.fromARGB(255, 240, 96, 96), content: Text( "Oops! Something went wrong. Reply not posted", style: TextStyle(color: Color.fromRGBO(255, 255, 255, 1)), ), ) ); } } } } catch(e){ print(e.toString()); // 也可以在这里添加mounted检查后显示错误弹窗 if(mounted){ ScaffoldMessenger.of(context).showSnackBar( const SnackBar( backgroundColor: Colors.red, content: Text("Network error occurred"), ) ); } } }
另一种方案:使用GlobalKey
如果不想依赖Widget的context,可以提前定义一个GlobalKey<ScaffoldMessengerState>,通过它来调用SnackBar:
- 在Widget类中定义全局Key:
final GlobalKey<ScaffoldMessengerState> _scaffoldKey = GlobalKey<ScaffoldMessengerState>();
- 在Scaffold中绑定这个Key:
Scaffold( key: _scaffoldKey, // ...其他代码 )
- 调用SnackBar时直接用Key:
_scaffoldKey.currentState?.showSnackBar(/* SnackBar内容 */);
这种方式不需要检查mounted,因为currentState会自动判断是否有效。
内容的提问来源于stack exchange,提问作者Cliff Odebala Clarke
相关产品推荐
相关产品推荐

