- 当执行异步操作,或者从下一个页面返回结果时,需要调用类似如下加载对话框代码,有时就会出现不能展示的问题,调式发现传入的
context 是无效的
/**
* showLoading()
* 加载对话框
*/
Future<T?> showLoadingAlert<T>(BuildContext context, Function task) async {
return await showDialog<T>(context: context, builder: (context) {
(() async {
Navigator.of(context).pop(await task(context));
})();
return UnconstrainedBox(
child: SizedBox(
width: 200,
child: AlertDialog(
content: Column(
mainAxisSize: MainAxisSize.min,
children: const [
CircularProgressIndicator(),
Padding(
padding: EdgeInsets.only(top: 20),
child: Text("加载中..."),
),
],
),
),
),
);
}, barrierDismissible: false);
}
- 如果想通过这样添加判断
mounted 解决,就会觉得实在不妥,因为这样不能保证顺利执行下去
if (!mounted) {
print('$c not mounted!');
//...
} else {
var result = await showLoadingAlert(context, () async {
//handler task
});
//...;
}
- 查过网上的资料,最后整理出来,改成如下这样试试,注意到
MyPage 页面代码中有定义了stateKey ,最后赋值给key 了,
class MyPage extends StatelessWidget with MixWidget {
final stateKey = GlobalKey<ScaffoldState>();
@override
Widget build(BuildContext context) {
return Scaffold(
key: stateKey,
//...
}
}
//...
Future<T?> showLoadingAlert<T>(Function(BuildContext context) task) async {
return await showDialog<T>(context: stateKey.currentContext!, builder: (context) {
(() async {
Navigator.of(context).pop(await task(context));
})();
return UnconstrainedBox(
child: SizedBox(
width: 200,
child: AlertDialog(
content: Column(
mainAxisSize: MainAxisSize.min,
children: const [
CircularProgressIndicator(),
Padding(
padding: EdgeInsets.only(top: 20),
child: Text("加载中..."),
),
],
),
),
),
);
}, barrierDismissible: false);
}
//...
}
- 运行以后,代码如下,只要调用
showLoadingAlert() 方法,不再传入context ,就能展示加载对话框了
onClick() async {
var result = await showLoadingAlert(() async {
//执行耗时请求
//...
});
//...;
}
- 最后,附上运行结果截图
|