【问题标题】:Managing errors on post in Flutter在 Flutter 中管理帖子中的错误
【发布时间】:2020-02-28 12:25:24
【问题描述】:

我为我工作的公司做了一个应用程序,该应用程序可以运行并解决了一些问题,但是代码很乱,因为我不是正式的程序员,这是我的第一个应用程序。现在我正在尝试改进代码。

这里的问题是我不知道如何检查http post是否成功。

在下面的代码中,您可以看到我进行了一些错误处理,但它无法正常工作。 例如,如果应用程序没有从服务器收到“ok”消息,它将返回一个错误,但如果互联网不工作,它不会返回错误,因为它将永远尝试发送帖子。 我想始终检查帖子是否成功并通知用户,或者在尝试一段时间后显示错误(比如 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();
                                      }),
                                ]);
                          });
                    }
                  })
            ],
          );
        },
      );
    }
  }```

【问题讨论】:

    标签: android flutter httprequest


    【解决方案1】:

    但如果互联网不工作,它不会返回错误,因为 它将永远尝试发送帖子。

    要解决这个问题,您要做的是为您的 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');
    }
    

    欢迎任何其他改进代码的提示。

    我建议制作一个单独的 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
      }
    

    【讨论】:

    • 感谢您的帮助!但我有一个问题。我已经实现了技巧 2,“创建类似 confirm_dialog.dart 的东西”,但是当我在 main 中调用该函数并确认该操作时,屏幕变黑。控制台显示错误:W/IInputConnectionWrapper(26828): getTextBeforeCursor on inactive InputConnection W/IInputConnectionWrapper(26828): getSelectedText on inactive InputConnection W/IInputConnectionWrapper(26828): getTextAfterCursor on inactive InputConnection
    • 不客气。您是否设法解决了问题,还是需要进一步的帮助?
    • 我需要帮助只是为了解决您建议的修改后的黑屏问题。
    • 哦,在我看到你的编辑之前写了我的评论。您是从有状态小部件还是无状态小部件调用 ConfirmDialog?
    • 我为您制作了一个简单的DartPad 来展示LinearProgressIndicatorCircularProgressIndicator。在 DartPad 中,您还可以找到一些简单的方法来控制应用程序的状态,具体取决于 post 方法的情况。
    【解决方案2】:

    我已经为 flutter 基础项目创建了示例项目,它的高度可维护性和干净的复制代码是链接

    https://github.com/SouravKumarPandit/flutter_base_project

    如果你不想要整个项目结构。你可以使用这个来获得干净和结构化的代码

    https://pub.dev/packages/mvvm_flutter#-installing-tab-

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2014-11-05
      • 1970-01-01
      • 2016-05-26
      • 1970-01-01
      • 1970-01-01
      • 2018-12-13
      • 2022-09-29
      相关资源
      最近更新 更多