在 Flutter 中管理 post 上的错误
Managing errors on post in Flutter
我为我工作的公司做了一个应用程序,该应用程序可以正常工作并解决了一些问题,但是代码很乱,因为我不是正式程序员,这是我的第一个应用程序。现在我正在努力改进代码。
这里的问题是我不知道如何检查 http post 是否成功。
在下面的代码中,您可以看到我做了一些错误处理,但它不能正常工作。
例如,如果应用程序没有从服务器收到 "ok" 消息,它将 return 一个错误,但如果互联网不工作,它不会 return 错误,因为它将永远尝试发送 post。
我想始终检查 post 是否成功并通知用户,或者在尝试一段时间后显示错误(比如 2 秒,我不知道),解决这个问题的最佳方法是什么?
欢迎任何其他改进代码的提示。
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,
);
} else if (_pecasList.length < 1) {
showDialog(
context: context,
builder: (BuildContext context) {
return AlertDialog(
title: new Text("Empty List"),
actions: <Widget>[
new FlatButton(
child: new Text("Close"),
onPressed: () {
Navigator.of(context).pop();
}),
]);
});
} else {
showDialog(
context: context,
builder: (BuildContext context) {
return AlertDialog(
title: new Text("Send the items?"),
actions: <Widget>[
new FlatButton(
child: new Text("Close"),
onPressed: () {
Navigator.of(context).pop();
}),
new FlatButton(
child: new Text("Send"),
onPressed: () async {
Map<String, dynamic> newDados = Map();
newDados["usuario"] = _usuarioController.text.trimLeft();
newDados["placa"] = _placaController.text.trimLeft();
newDados["box"] = _boxController.text.trimLeft();
newDados["tipo_veiculo"] = dropdownValue1;
_dadosList.add(newDados);
print(_pecasList + _dadosList);
Map<String, String> headers = new Map<String, String>();
headers["Content-type"] = "application/json";
headers["Accept"] = "application/json";
//String str = '{"take":55, "skip":"0"}';
final resp = await http.post('http://' + ipServidor,
body: jsonEncode(_dadosList +
_pecasList), //+ jsonEncode(_pecasList),
headers: headers);
print(resp.statusCode);
_dadosList
.clear(); //Cleans the list
print(resp.body);
if (resp.statusCode == 200) {
if (resp.body == "ok") {
setState(() {
print(_pecasList);
_pecasList.clear();
_placaController.clear();
_boxController.clear();
dropdownValue1 = "Vehicle type";
Navigator.of(context).pop();
});
} else {
showDialog(
context: context,
builder: (BuildContext context) {
return AlertDialog(
title: new Text(
"Error"),
actions: <Widget>[
new FlatButton(
child: new Text("Close"),
onPressed: () {
Navigator.of(context).pop();
Navigator.of(context).pop();
}),
]);
});
}
} else {
print("communication error");
Navigator.of(context).pop();
showDialog(
context: context,
builder: (BuildContext context) {
return AlertDialog(
title: new Text("communication error"),
actions: <Widget>[
new FlatButton(
child: new Text("Close"),
onPressed: () {
Navigator.of(context).pop();
}),
]);
});
}
})
],
);
},
);
}
}```
我已经为 flutter 基础项目 创建了示例项目,它具有高度的可维护性和干净性,复制这里的代码是 link
https://github.com/SouravKumarPandit/flutter_base_project
如果你不想要整个项目 structure.you 可以使用这个 包 以获得干净和结构化的代码
but if the internet isnt working it will not return the error because
it will be trying forever to send the post.
要解决这个问题,您要做的是为您的 http 调用添加超时。
int timeout = 10;
try {
http.Response response = await http.post('http://' + ipServidor,
headers: headers,
body: jsonEncode(_dadosList + _pecasList), encoding: utf8).
timeout(Duration(seconds: timeout));
if (response.statusCode == 200) {
// do something
} else {
// handle it
}
} on TimeoutException catch (e) {
print('Timeout Error: $e');
} on SocketException catch (e) {
print('Socket Error: $e');
} on Error catch (e) {
print('General Error: $e');
}
Any other tips to improve the code are welcome.
我建议制作一个单独的 dart 文件,其中包含用于将在您的应用中重复出现的代码的不同部分的方法。
1) 创建类似于 http_handler.dart 的东西,它将具有异步方法 httpPost 和 httpGet。示例:
httpGet(String url, int attempts, int timeout) async {
var parsedJson;
bool success = false;
int attempt=0;
while(!success && attempt<attempts) {
attempt++;
// your httpGet try catch block
// inside of it -> if response == 200 then success = true
// also parse your json here
if(!success) {
sleep(const Duration(milliseconds: 500)); //sleep a bit between attempts
}
}
return parsedJson;
}
2) 创建类似于 confirm_dialog.dart
的内容
import 'package:flutter/material.dart';
enum ConfirmAction { CANCEL, ACCEPT }
Future<ConfirmAction> ConfirmDialog(BuildContext context, String title, String content) async {
return showDialog<ConfirmAction>(
context: context,
barrierDismissible: false, // user must tap on a button to close the dialog!
builder: (BuildContext context) {
return AlertDialog(
title: Text(title),
content: Text(content),
actions: <Widget>[
FlatButton(
child: Text("NO"),
onPressed: () {
Navigator.of(context).pop(ConfirmAction.CANCEL);
},
),
FlatButton(
child: Text("YES"),
onPressed: () {
Navigator.of(context).pop(ConfirmAction.ACCEPT);
},
)
],
);
},
);
}
然后当您需要用户确认或取消操作时,您可以像这样使用它:
ConfirmAction action = await ConfirmDialog(context, "Dialog Title", "Dialog Content");
if (action == ConfirmAction.ACCEPT) {
//do something
}
我为我工作的公司做了一个应用程序,该应用程序可以正常工作并解决了一些问题,但是代码很乱,因为我不是正式程序员,这是我的第一个应用程序。现在我正在努力改进代码。
这里的问题是我不知道如何检查 http post 是否成功。
在下面的代码中,您可以看到我做了一些错误处理,但它不能正常工作。 例如,如果应用程序没有从服务器收到 "ok" 消息,它将 return 一个错误,但如果互联网不工作,它不会 return 错误,因为它将永远尝试发送 post。 我想始终检查 post 是否成功并通知用户,或者在尝试一段时间后显示错误(比如 2 秒,我不知道),解决这个问题的最佳方法是什么?
欢迎任何其他改进代码的提示。
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,
);
} else if (_pecasList.length < 1) {
showDialog(
context: context,
builder: (BuildContext context) {
return AlertDialog(
title: new Text("Empty List"),
actions: <Widget>[
new FlatButton(
child: new Text("Close"),
onPressed: () {
Navigator.of(context).pop();
}),
]);
});
} else {
showDialog(
context: context,
builder: (BuildContext context) {
return AlertDialog(
title: new Text("Send the items?"),
actions: <Widget>[
new FlatButton(
child: new Text("Close"),
onPressed: () {
Navigator.of(context).pop();
}),
new FlatButton(
child: new Text("Send"),
onPressed: () async {
Map<String, dynamic> newDados = Map();
newDados["usuario"] = _usuarioController.text.trimLeft();
newDados["placa"] = _placaController.text.trimLeft();
newDados["box"] = _boxController.text.trimLeft();
newDados["tipo_veiculo"] = dropdownValue1;
_dadosList.add(newDados);
print(_pecasList + _dadosList);
Map<String, String> headers = new Map<String, String>();
headers["Content-type"] = "application/json";
headers["Accept"] = "application/json";
//String str = '{"take":55, "skip":"0"}';
final resp = await http.post('http://' + ipServidor,
body: jsonEncode(_dadosList +
_pecasList), //+ jsonEncode(_pecasList),
headers: headers);
print(resp.statusCode);
_dadosList
.clear(); //Cleans the list
print(resp.body);
if (resp.statusCode == 200) {
if (resp.body == "ok") {
setState(() {
print(_pecasList);
_pecasList.clear();
_placaController.clear();
_boxController.clear();
dropdownValue1 = "Vehicle type";
Navigator.of(context).pop();
});
} else {
showDialog(
context: context,
builder: (BuildContext context) {
return AlertDialog(
title: new Text(
"Error"),
actions: <Widget>[
new FlatButton(
child: new Text("Close"),
onPressed: () {
Navigator.of(context).pop();
Navigator.of(context).pop();
}),
]);
});
}
} else {
print("communication error");
Navigator.of(context).pop();
showDialog(
context: context,
builder: (BuildContext context) {
return AlertDialog(
title: new Text("communication error"),
actions: <Widget>[
new FlatButton(
child: new Text("Close"),
onPressed: () {
Navigator.of(context).pop();
}),
]);
});
}
})
],
);
},
);
}
}```
我已经为 flutter 基础项目 创建了示例项目,它具有高度的可维护性和干净性,复制这里的代码是 link
https://github.com/SouravKumarPandit/flutter_base_project
如果你不想要整个项目 structure.you 可以使用这个 包 以获得干净和结构化的代码
but if the internet isnt working it will not return the error because it will be trying forever to send the post.
要解决这个问题,您要做的是为您的 http 调用添加超时。
int timeout = 10;
try {
http.Response response = await http.post('http://' + ipServidor,
headers: headers,
body: jsonEncode(_dadosList + _pecasList), encoding: utf8).
timeout(Duration(seconds: timeout));
if (response.statusCode == 200) {
// do something
} else {
// handle it
}
} on TimeoutException catch (e) {
print('Timeout Error: $e');
} on SocketException catch (e) {
print('Socket Error: $e');
} on Error catch (e) {
print('General Error: $e');
}
Any other tips to improve the code are welcome.
我建议制作一个单独的 dart 文件,其中包含用于将在您的应用中重复出现的代码的不同部分的方法。
1) 创建类似于 http_handler.dart 的东西,它将具有异步方法 httpPost 和 httpGet。示例:
httpGet(String url, int attempts, int timeout) async {
var parsedJson;
bool success = false;
int attempt=0;
while(!success && attempt<attempts) {
attempt++;
// your httpGet try catch block
// inside of it -> if response == 200 then success = true
// also parse your json here
if(!success) {
sleep(const Duration(milliseconds: 500)); //sleep a bit between attempts
}
}
return parsedJson;
}
2) 创建类似于 confirm_dialog.dart
的内容import 'package:flutter/material.dart';
enum ConfirmAction { CANCEL, ACCEPT }
Future<ConfirmAction> ConfirmDialog(BuildContext context, String title, String content) async {
return showDialog<ConfirmAction>(
context: context,
barrierDismissible: false, // user must tap on a button to close the dialog!
builder: (BuildContext context) {
return AlertDialog(
title: Text(title),
content: Text(content),
actions: <Widget>[
FlatButton(
child: Text("NO"),
onPressed: () {
Navigator.of(context).pop(ConfirmAction.CANCEL);
},
),
FlatButton(
child: Text("YES"),
onPressed: () {
Navigator.of(context).pop(ConfirmAction.ACCEPT);
},
)
],
);
},
);
}
然后当您需要用户确认或取消操作时,您可以像这样使用它:
ConfirmAction action = await ConfirmDialog(context, "Dialog Title", "Dialog Content");
if (action == ConfirmAction.ACCEPT) {
//do something
}