Flutter使用RaisedButton向Firestore发数据时如何添加发送前置校验规则
现有代码存在的核心逻辑问题
- 网络检查方法
check()没有被正确使用:方法签名标注了返回Future<bool>,但内部没有任何返回语句,调用时既没有await等待结果,也没有读取返回值做判断,网络状态根本不会拦截上传流程 - 状态变量职责混淆:原本用来存网络状态提示的
internetdisponible变量,同时被用来存上传成功的提示文案,会出现断网时弹窗显示“上传成功”的错配问题 - 流程顺序错误:当前代码没有将网络连通性检查纳入前置拦截逻辑,只要表单校验通过就会直接触发Firestore上传,完全忽略网络异常场景
- 异步调用没有等待:直接调用
check()没有await,网络检查还没返回结果就已经开始执行后续上传逻辑,判断完全失效
修复实现
1. 重构网络检查工具方法
拆分状态提示和网络判断的职责,让方法直接返回连通性布尔结果:
Future<bool> checkNetworkConnectivity() async { try { final result = await InternetAddress.lookup('google.com'); return result.isNotEmpty && result[0].rawAddress.isNotEmpty; } on SocketException catch (_) { return false; } }
2. 调整按钮点击的校验流程
将必填项校验、网络连通性校验全部放在上传逻辑之前,任意一项不满足就直接终止执行,不触发数据库写入:
RaisedButton( color: Color(0xff11b719), textColor: Colors.white, child: Padding( padding: EdgeInsets.all(10.0), child: Row( mainAxisAlignment: MainAxisAlignment.spaceEvenly, children: <Widget>[ Text("Envoyer ", style: TextStyle(fontSize: 18.0)), ], )), onPressed: () async { // 第一步:校验必填字段 final isFormPassed = medicalType != null && validatetextfield(nomdata.text) == true && validatetextfield(mobiledata.text) == true && validatetextfield(addressedata.text) == true; if (!isFormPassed) { ScaffoldMessenger.of(context).showSnackBar(const SnackBar( content: Text("SVP Remplir tout les champs"))); return; } // 第二步:校验网络连通性,断网直接拦截 final isNetworkConnected = await checkNetworkConnectivity(); if (!isNetworkConnected) { ScaffoldMessenger.of(context).showSnackBar(const SnackBar( content: Text("Vérifier Votre connexion internet Svp"))); return; } // 两个校验全部通过后,才执行数据上传 Map<String, dynamic> data = { "specialité": medicalType, "Nom:": nomdata.text, "Téléphone:": mobiledata.text, "adresse:": addressedata.text, "autre:": autredata.text, }; var myStoredData = await readData(); await FirebaseFirestore.instance .collection(myStoredData) .add(data); // 上传成功后弹出成功提示 showDialog( context: context, builder: (context) { return AlertDialog( title: const Text('vous avez ajouté un nouveau medcin \n MERCI', style: TextStyle(fontSize: 14.0), textAlign: TextAlign.center), actions: <Widget>[ FlatButton( child: const Text('OK'), onPressed: () { Navigator.of(context).pop(); }, ) ], ); }, ); }, shape: RoundedRectangleBorder( borderRadius: BorderRadius.circular(30.0))),
补充优化建议
RaisedButton属于已废弃组件,后续可替换为官方推荐的ElevatedButton实现相同视觉效果- 目前通过DNS lookup google.com判断网络的方式,在特定网络场景下可能存在连通性判断偏差,可根据实际部署环境调整检查的域名
- 给Firestore的写入操作增加异常捕获逻辑,避免写入失败时应用无响应,也能针对性给出错误提示
内容的提问来源于stack exchange,提问作者flutter 87
相关产品推荐
相关产品推荐

