Flutter基于Dio实现登录时遇400错误无法获取后端响应数据
Dio 400 状态码场景下提取后端业务响应的方案
核心问题原因
Dio 默认的响应校验逻辑,会将所有不属于 2xx 范围的HTTP状态码直接抛出为DioException错误,请求不会走到try块的正常响应分支。你代码里写的if (res.statusCode == 400) 判断逻辑永远不会被执行,触发400状态码时会直接跳转到catch块,自然拿不到正常响应对象。
可行解决方法
方法1:从捕获的DioException中提取响应数据
这是通用性最强的方案,不需要改动全局Dio配置,只需要在catch块中对异常类型做判断,直接读取异常对象携带的后端响应内容:
修改后的登录方法实现:
Future login(String username, String password) async { try { String url = "$baseUrl/admin/user/login"; print(url); var res = await dio.post( url, data: {"email": username, "password": password}, ); print(res.data); return true; } catch (e, s) { // 识别Dio抛出的请求类异常 if (e is DioException) { final errResponse = e.response; // 仅当拿到后端返回的响应时解析业务数据 if (errResponse != null) { // 匹配400状态码的业务错误场景 if (errResponse.statusCode == 400) { // 直接读取后端返回的结构化业务数据 final errBizData = errResponse.data; print(errBizData); // 可直接取对应字段值,比如errBizData["message"] return false; } } } print("stacktrace $s"); print("error $e"); return false; } }
注意事项:
- 必须对
e.response做非空判断:网络断连、请求超时、DNS解析失败这类没有拿到后端返回的异常,response字段为null,直接读取会触发空指针错误 - 该方案适配零散的状态码处理场景,不会影响项目其他请求的默认错误逻辑
方法2:调整Dio全局状态码校验规则
如果项目接口普遍将400作为业务逻辑错误的返回状态码,不想每次都在catch块中重复写判断逻辑,可以在Dio初始化时自定义校验规则,让Dio不要把指定范围的状态码判定为错误,直接走正常响应返回流程:
// Dio初始化配置示例 final dio = Dio( BaseOptions( baseUrl: baseUrl, // 自定义状态码校验规则 validateStatus: (status) { // 规则:200~399状态码正常返回不抛错,同时将400状态码纳入不抛错范围 return status != null && (status >= 200 && status < 400 || status == 400); }, ), );
配置完成后,你原本写的if (res.statusCode == 400) 分支逻辑就可以正常执行,触发400状态码时不会直接抛异常进入catch块。
注意事项:
- 不建议将所有4xx、5xx状态码都设置为不抛错,否则500服务器内部错误、404接口不存在这类系统级错误,也需要手动判断状态码,反而增加冗余逻辑
- 该全局配置会影响所有使用当前Dio实例的请求,需要和项目内的接口状态码约定保持一致
内容的提问来源于stack exchange,提问作者Mr. ZeroOne
相关产品推荐
相关产品推荐

