Flutter中如何在await调用后正常显示AlertDialog?
解决await ImagePicker后AlertDialog不显示的问题
这个问题我之前也碰到过,本质原因是await图片选择操作后,你原来使用的context可能已经失效或者不再处于挂载状态了。ImagePicker的原生界面会暂时切换到系统相册,这期间你的Flutter widget可能因为状态重建、或者context关联的widget被销毁,导致后续调用showDialog时传入的context已经无效,对话框自然就弹不出来了。
下面给你几个可行的解决方案:
方案1:使用GlobalKey获取稳定的Context
给你的父级Scaffold(或者页面的根widget)设置一个GlobalKey,这样不管widget怎么重建,都能通过key拿到有效的context:
// 在State类里定义GlobalKey final GlobalKey<ScaffoldState> _scaffoldKey = GlobalKey<ScaffoldState>(); // 在build方法里给Scaffold赋值key @override Widget build(BuildContext context) { return Scaffold( key: _scaffoldKey, // ...其他页面代码 ); } // 修改后的selectImage方法 void selectImage() async { var _fileName = await ImagePicker.pickImage( source: ImageSource.gallery, maxWidth: 250.0, maxHeight: 250.0 ); // 使用GlobalKey获取的有效context showDialog( context: _scaffoldKey.currentContext!, builder: (BuildContext context) => AlertDialog( content: const Text("Random question?"), actions: <Widget>[ FlatButton( onPressed: () => Navigator.of(context).pop(), child: const Text("Close") ) ] ) ); }
方案2:检查Widget是否挂载(StatefulWidget适用)
如果你的方法在State类里,可以先通过mounted属性判断当前widget是否还处于挂载状态,再调用showDialog:
void selectImage() async { var _fileName = await ImagePicker.pickImage( source: ImageSource.gallery, maxWidth: 250.0, maxHeight: 250.0 ); // 先确认widget还在挂载状态,避免无效context if (!mounted) return; showDialog( context: context, builder: (BuildContext context) => AlertDialog( content: const Text("Random question?"), actions: <Widget>[ FlatButton( onPressed: () => Navigator.of(context).pop(), child: const Text("Close") ) ] ) ); }
方案3:使用根导航的Context
调用Navigator.of(context, rootNavigator: true)获取根导航的context,这样可以避开当前widget context失效的问题:
void selectImage() async { var _fileName = await ImagePicker.pickImage( source: ImageSource.gallery, maxWidth: 250.0, maxHeight: 250.0 ); showDialog( // 使用根导航的稳定context context: Navigator.of(context, rootNavigator: true).context, builder: (BuildContext context) => AlertDialog( content: const Text("Random question?"), actions: <Widget>[ FlatButton( onPressed: () => Navigator.of(context).pop(), child: const Text("Close") ) ] ) ); }
另外小提醒:如果你用的是较新版本的image_picker插件,pickImage方法已经被废弃了,建议换成pickImageFromGallery或者pickMedia方法,不过这和当前的对话框问题无关~
内容的提问来源于stack exchange,提问作者X09
相关产品推荐
相关产品推荐

