Flutter中HTTP Post请求错误处理优化及代码改进咨询
你好!先解决你最头疼的HTTP请求超时和错误判断问题,再给你一些代码优化的建议,让你的应用更健壮、代码更好维护。
核心问题解决:可靠的请求状态判断与超时处理
你的代码目前只处理了服务器返回状态码的情况,但无网络、服务器不可达、请求超时这类场景会直接抛出异常,不会进入状态码判断逻辑,导致请求阻塞且无提示。我们可以通过「超时设置+异常捕获」的组合解决这个问题:
修改后的请求核心代码
new FlatButton( child: new Text("Send"), onPressed: () async { // 先关闭确认对话框 Navigator.of(context).pop(); // 显示加载提示,提升用户感知 showDialog( context: context, barrierDismissible: false, builder: (ctx) => AlertDialog(title: Text("Sending...")), ); Map<String, dynamic> newDados = {}; newDados["usuario"] = _usuarioController.text.trim(); newDados["placa"] = _placaController.text.trim(); newDados["box"] = _boxController.text.trim(); newDados["tipo_veiculo"] = dropdownValue1; _dadosList.add(newDados); final headers = { "Content-type": "application/json", "Accept": "application/json" }; try { // 设置2秒超时,同时用Uri.parse规范URL拼接 final resp = await http.post( Uri.parse('http://$ipServidor'), body: jsonEncode(_dadosList + _pecasList), headers: headers, ).timeout(const Duration(seconds: 2)); print(resp.statusCode); _dadosList.clear(); print(resp.body); // 关闭加载对话框 Navigator.of(context).pop(); // 处理服务器响应 if (resp.statusCode == 200) { if (resp.body == "ok") { setState(() { _pecasList.clear(); _placaController.clear(); _boxController.clear(); dropdownValue1 = "Vehicle type"; }); Toast.show("\n Sent successfully! \n", context, duration: Toast.LENGTH_LONG, gravity: Toast.CENTER, backgroundRadius: 5.0); } else { _showAlert(context, "Error", "Server returned unexpected response"); } } else { _showAlert(context, "Communication Error", "Server error: ${resp.statusCode}"); } } on TimeoutException { // 捕获超时异常 Navigator.of(context).pop(); _showAlert(context, "Timeout", "Request timed out, please try again"); } on SocketException { // 捕获无网络/服务器不可达异常 Navigator.of(context).pop(); _showAlert(context, "Network Error", "No internet or server is unreachable"); } catch (e) { // 捕获其他所有未知异常 Navigator.of(context).pop(); _showAlert(context, "Unexpected Error", "Something went wrong: ${e.toString()}"); } }, ), // 通用弹窗工具函数,避免重复代码 void _showAlert(BuildContext context, String title, String content) { showDialog( context: context, builder: (ctx) => AlertDialog( title: Text(title), content: Text(content), actions: [ FlatButton( child: const Text("Close"), onPressed: () => Navigator.of(ctx).pop(), ), ], ), ); }
关键改进点
- 添加
timeout设置,2秒未响应自动触发超时提示 - 用
try-catch精准捕获不同类型的异常,覆盖所有失败场景 - 新增加载对话框,让用户明确知道请求正在进行
- 用
Uri.parse替代字符串拼接URL,避免格式错误 - 提取通用弹窗函数,减少代码重复
其他代码优化建议
作为首个应用,你的代码能跑通已经很棒了,以下建议能让代码更易维护:
1. 拆分逻辑为独立函数
把输入验证、请求发送这类重复/复杂逻辑拆成单独函数,让主代码更简洁:
// 输入验证函数 bool _validateInputs() { if (_usuarioController.text.isEmpty || _placaController.text.isEmpty || _boxController.text.isEmpty || dropdownValue1 == "Vehicle type") { Toast.show("\n Complete all fields \n", context, duration: Toast.LENGTH_LONG, gravity: Toast.CENTER, backgroundRadius: 5.0); return false; } if (_pecasList.isEmpty) { _showAlert(context, "Empty List", "Please add items first"); return false; } return true; }
2. 使用空安全语法
Dart现在推荐空安全,把Map()改成{}或Map<String, dynamic>(),避免潜在空指针问题。
3. 优化输入处理
用trim()替代trimLeft(),同时可以给输入框添加输入格式校验(比如车牌号格式),提前拦截无效输入。
4. 避免硬编码字符串
把提示文本、按钮文字抽成常量,方便后续修改和国际化:
const String kCompleteAllFields = "\n Complete all fields \n"; const String kEmptyListTitle = "Empty List";
5. 代码格式化
用VS Code的Ctrl+Shift+F(或Android Studio的Ctrl+Alt+L)自动格式化代码,让缩进、换行更规范,可读性大幅提升。
内容的提问来源于stack exchange,提问作者abrev
相关产品推荐
相关产品推荐

