【问题标题】:Flutter : Handling error Dio Package (404,400 etc)Flutter:处理错误 Dio 包(404,400 等)
【发布时间】:2019-12-18 17:04:47
【问题描述】:

我正在学习使用包DIO https://pub.dev/packages/dio按ID搜索数据,我的问题是每次输入错误的关键字搜索时,应用程序突然崩溃并显示调试消息404 Not找到


我知道没有找到数据,因为我输入了错误的关键字,但我已经用这段代码处理了这个问题

Widget _searchKeywordMahasiswa() {
    return FutureBuilder<List<Mosque>>(
      future: api.getMahasiswaById(_searchText),
      builder: (BuildContext context, AsyncSnapshot snapshot) {
        if (snapshot.hasData) {
          return Expanded(
            child: ListView.builder(
              shrinkWrap: true,
              itemCount: snapshot.data.length,
              itemBuilder: (BuildContext context, int index) {
                return Text(snapshot.data[index].id);
              },
            ),
          );
        } else if (!snapshot.data) { <<<<<< IN THIS LINE
          return Center(
            child: Icon(
              Icons.sentiment_very_dissatisfied,
              size: 150.0,
            ),
          );
        }
        return CircularProgressIndicator();
      },
    );
    // return CircularProgressIndicator();
  }
Future<List<Mosque>> getMahasiswaById(String id) async{
    try {
      var apiRespon = await dio.get('${Urls.BASE_API_URL}/mahasiswa/get/id/$id');
      var apiResponJson = apiRespon.data;
      print(apiResponJson);
      return (apiResponJson['data'] as List).map((p)=>Mosque.fromJson(p)).toList();

    }on DioError catch (e) { <<<<< IN THIS LINE
      if(e.response.statusCode == 404){
        print(e.response.statusCode);
      }else{
        print(e.message);
        print(e.request);
      }
    }
  }

在同样的情况下,如果我收到错误 400 Bad Request 我的应用程序也会崩溃,而且我已经在处理这个错误但无法正常工作。

你能帮帮我吗?

【问题讨论】:

  • 请打印此变量 ${Urls.BASE_API_URL}/mahasiswa/get/id/$id 的内容并将其粘贴到您的浏览器。和“添加评论”让我在您完成此步骤时进行跟踪。谢谢。
  • @chunhunghan 当我将http://192.168.43.159/wpu-rest-server/apii/mahasiswa/get/ID/$id 粘贴到浏览器中时。告诉我An Error Was Encountered. The URI you submitted has disallowed characters.
  • 请将 $id 更改为真实存在的 id,例如 123 或字符串,然后重做。
  • @chunhunghan 如果我粘贴 http://192.168.43.159/wpu-rest-server/apii/mahasiswa/get/id/5 按 id 5 显示数据
  • 在 catch 上抛出错误怎么样?并添加 snapshot.hasError?关于futurebuilder的if else语句

标签: flutter dart


【解决方案1】:
 var response = await dio.delete(
          url,
          data: postData,
          options: Options(
            followRedirects: false,
            validateStatus: (status) {
              return status < 500;
            },
            headers: headers,
          ),
        );

兄弟,请使用下面的代码,

将 followRedirects、validateStatus 添加到您的代码中。

【讨论】:

  • 不确定这是正确的方法。但是兄弟!它对我有用。
  • 这是一个棘手的答案,绝对有效,但不是专业的,我刚刚在这个问题下方发布了一个由 Dio 自己推荐的答案。希望你能接受。
【解决方案2】:

删除 'on DioError' - 不幸的是,有一些错误(404's、500s ...)Dio 不会处理也不会捕获 - 在我的应用程序中也有类似的问题。 然后将代码更改为发布在下面或使用其他一些逻辑来“抓住所有”;)

} catch (e) {

    if (e is DioError) {
    //handle DioError here by error type or by error code

    } else {
    ...
    }
 //return empty list (you can also return custom error to be handled by Future Builder)
}

顺便说一句,您应该正确处理 Future Builder 状态:snapshot.hasData、空数据和 snapshot.hasError 在您的未来构建器中以防止未来崩溃

【讨论】:

  • 请您举例说明我在 ifelse 语句中可以做什么?我可以在 if 语句 return nullelse 语句中插入什么我要插入 return true ?要不然是啥 ?谢谢
  • 我已经关注你的代码了,如果我输入错误的关键字,我的应用程序仍然会崩溃。
  • 并确保声明正确的 ulr - 404 表示未找到。不幸的是,我目前无法在 AndroidStudio 中检查您的代码
  • 你能检查我的答案吗,为什么如果我使用 http.get 我的代码它可以工作,但在 DIO 中它会崩溃?我尝试将http.get 替换为dio.get 并且仍然面临错误?
  • 您提供的信息还不够...如果您得到的是 400,这意味着您的 api 调用(url、正文、标题等)有问题 - 双/三检查一下
【解决方案3】:

此 URL 字符串模式 ${Urls.BASE_API_URL}/mahasiswa/get/id/$id 出错

你不能使用 .运算符并从“”内的任何对象访问内部值。您可以将确切的 url 存储在其他变量中并在该行中使用它。代码应该如下。

Future<List<Mosque>> getMahasiswaById(String id) async{
try {
  var baseURL = Urls.BASE_API_URL;
  var apiRespon = await dio.get('${baseURL}/mahasiswa/get/id/$id');
  var apiResponJson = apiRespon.data;
  print(apiResponJson);
  return (apiResponJson['data'] as List).map((p)=>Mosque.fromJson(p)).toList();

}on DioError catch (e) { <<<<< IN THIS LINE
  if(e.response.statusCode == 404){
    print(e.response.statusCode);
  }else{
    print(e.message);
    print(e.request);
  }
}
}

【讨论】:

  • 你能检查我的答案吗,为什么如果我使用 http.get 我的代码它可以工作,但在 DIO 中它会崩溃?我尝试用dio.get 替换http.get 仍然面临错误?
  • 。运算符可以在 '' 中使用
【解决方案4】:

我遇到了同样的问题,只是更改了有效的拦截器

import 'package:dio/dio.dart';

class CustomInterceptor extends Interceptor {
  @override
  void onRequest(RequestOptions options, RequestInterceptorHandler handler) async {
    print("onRequest");
    return super.onRequest(options, handler);
  }

  @override
  Future onResponse(Response response, ResponseInterceptorHandler handler) {
    print("onResponse");
    return null;
  }

  @override
  Future onError(DioError err, ErrorInterceptorHandler handler) async {
    print("onError: ${err.response.statusCode}");
    return handler.next(err);  // <--- THE TIP IS HERE
  }
}

【讨论】:

    【解决方案5】:

    您可以使用DioClient 管理超时异常:

    有两种方法,声明自定义的Option 然后分配给Dio 或直接在下面分配option 给它,但我更喜欢将这些类型的Option 分开来满足需要。 您可以设置一个条件来获取除 400(成功)响应之外的所有问题,但您必须注意 Connection Timeout,所以这里集成了 Dio 方式:

    class YourRepositary {
      Dio dioClient;
    
      YourRepositary() {
        if (dioClient == null) {
          BaseOptions options = new BaseOptions(
              baseUrl: "YOUR_APIs_BASE_URL",
              receiveDataWhenStatusError: true,
              connectTimeout: 30000, // 30 seconds
              receiveTimeout: 30000 // 30 seconds
              );
    
          dioClient = new Dio(options);
        }
      }
    
      Future<ProductResponseModel> getProduct(var productRequestInputDto) async {
        try {
          Response response = await dio.post("/api/getProduct", data: productRequestInputDto);
          final ProductResponseModel _productModel = ProductResponseModel.fromJson(response.data);
          return _productModel ;
        } on DioError  catch (ex) {
          if(ex.type == DioErrorType.CONNECT_TIMEOUT){
            throw Exception("Connection Timeout Exception");
          }
          throw Exception(ex.message);
        }
      }
    
    }
    

    最后,下面的示例演示了如何处理超时异常,甚至在 API 调用中被后端 500 错误处理:

    void getProduct(){
     ProductRequestInputDto productRequest = new ProductRequestInputDto(productId: "666");
    
            var requestBody = jsonEncode(loginRequest);
            debugPrint("Request Data : $requestBody");
    
            _apiRepositary.getProduct(requestBody).then((response){
              debugPrint("Login Success $response");
              //manage your response here 
             },
              onError: (exception){
                  //Handle exception message
                if(exception.message != null ){
                  debugPrint(exception.message); // Here you get : "Connection  Timeout Exception" or even handled 500 errors on your backend.
                }
              },
            );
    }
    

    总之,这一切都与receiveDataWhenStatusError: true有关,在Dio的选项中。

    【讨论】:

      【解决方案6】:

      我也有类似的类型问题。

      首先,尝试在命令提示符下使用flutter run 运行项目,看看是否出现任何问题。

      如果命令提示符显示没有问题并且您的应用程序运行顺利,那么您必须检查 IDE。如果您使用的是 VSCode,则切换到 Debug is side bar,查看 Breakpoint 部分中勾选了哪些选项。如果All Exceptions 被勾选,那么调试器将在每次异常时暂停。取消选中 All ExceptionsUncaught Exceptions 然后尝试刷新重启。

      希望这能解决您的问题。

      【讨论】:

        【解决方案7】:

        找到了解决办法。这段代码对我有用。

        try {
          Dio dio = Dio();
          var res = await dio.download(
            url + 'fg',
            savePath.path + "/filename.bin",
            onReceiveProgress: (count, total) {
              progress(count, total);
            },
          );
        } on DioError catch (e) {
          if (e.type == DioErrorType.response) {
            print('catched');
            return;
          }
          if (e.type == DioErrorType.connectTimeout) {
            print('check your connection');
            return;
          }
        
          if (e.type == DioErrorType.receiveTimeout) {
            print('unable to connect to the server');
            return;
          }
        
          if (e.type == DioErrorType.other) {
            print('Something went wrong');
            return;
          }
          print(e);
        } catch (e) {
          print(e);
        }
        

        【讨论】:

          【解决方案8】:
            dynamic _decodeErrorResponse(dynamic e) {
              dynamic data = {"statusCode": -1, "message": "Unknown Error"};
              if (e is DioError) {
                if (e.type == DioErrorType.response) {
                  final response = e.response;
                  try {
                    if (response != null && response.data != null) {
                      final Map responseData =
                          json.decode(response.data as String) as Map;
                      data["message"] = responseData['message'] as String;
                      data["statusCode"] = response.statusCode;
                    }
                  } catch (e) {
                    data["message"] = "Internal Error Catch";
                  }
                } else if (e.type == DioErrorType.connectTimeout ||
                    e.type == DioErrorType.receiveTimeout ||
                    e.type == DioErrorType.sendTimeout) {
                  data["message"] = "Request timeout";
                  data["statusCode"] = 408;
                } else if (e.error is SocketException) {
                  data["message"] = "No Internet Connection!";
                }
              }
              return data;
            }
          

          【讨论】:

            【解决方案9】:

            所选答案运行良好。但是如果有人在添加这些行后仍然出现错误。你可以试试这个。

            向字段添加内容类型。

            dio.FormData formData = dio.FormData.fromMap({
                  "file": await dio.MultipartFile.fromFile(
                    file.path,
                    filename: fileName,
                    contentType: MediaType('audio', 'mp4'),
                  ),
            

            【讨论】:

              猜你喜欢
              • 2020-01-17
              • 2021-09-06
              • 2021-09-07
              • 2023-01-28
              • 1970-01-01
              • 2020-06-29
              • 1970-01-01
              • 2021-07-14
              • 2021-09-29
              相关资源
              最近更新 更多