在鸿蒙应用开发中,网络请求是必不可少的部分。每次API调用后,我们都需要处理各种HTTP状态码。传统做法是直接在代码中硬编码状态码数字,比如:
dart复制if (response.statusCode == 200) {
// 处理成功逻辑
} else if (response.statusCode == 404) {
// 处理未找到资源
}
这种做法存在几个明显问题:
http_status库正是为了解决这些问题而设计的。它将HTTP协议中定义的状态码封装为有意义的常量,让代码更清晰、更易维护。
HTTP状态码按照RFC标准分为五大类:
http_status库为每一类状态码都提供了判断方法:
dart复制HttpStatus.isInformational(code); // 1xx
HttpStatus.isSuccess(code); // 2xx
HttpStatus.isRedirect(code); // 3xx
HttpStatus.isClientError(code); // 4xx
HttpStatus.isServerError(code); // 5xx
库中的常量命名严格遵循RFC文档中的官方描述,例如:
HttpStatus.ok对应200HttpStatus.notFound对应404HttpStatus.internalServerError对应500这种命名方式使得代码几乎可以自解释,大大降低了理解成本。
添加依赖非常简单,只需要执行:
bash复制flutter pub add http_status
或者在pubspec.yaml中手动添加:
yaml复制dependencies:
http_status: ^最新版本号
dart复制import 'package:http_status/http_status.dart';
if (response.statusCode == HttpStatus.ok) {
// 处理成功响应
}
dart复制var status = HttpStatus.fromCode(response.statusCode);
print(status.name); // 输出状态码的名称,如"OK"、"Not Found"等
dart复制if (HttpStatus.isSuccess(response.statusCode)) {
// 处理所有2xx的成功响应
}
dart复制import 'package:dio/dio.dart';
import 'package:http_status/http_status.dart';
class SemanticInterceptor extends Interceptor {
@override
void onResponse(Response response, ResponseInterceptorHandler handler) {
final status = HttpStatus.fromCode(response.statusCode);
if (!status.isSuccess) {
// 统一处理非成功响应
throw DioError(
requestOptions: response.requestOptions,
response: response,
type: DioErrorType.badResponse,
error: '请求失败: ${status.name}',
);
}
super.onResponse(response, handler);
}
@override
void onError(DioError err, ErrorInterceptorHandler handler) {
final statusCode = err.response?.statusCode;
if (statusCode != null) {
final status = HttpStatus.fromCode(statusCode);
// 根据不同类型的状态码进行特殊处理
switch (status.code) {
case HttpStatus.unauthorized.code:
// 处理认证失败
break;
case HttpStatus.tooManyRequests.code:
// 处理请求过多
break;
default:
break;
}
}
super.onError(err, handler);
}
}
dart复制void setupDio() {
final dio = Dio();
dio.interceptors.add(SemanticInterceptor());
// 全局错误处理
dio.interceptors.add(InterceptorsWrapper(
onError: (error, handler) {
final statusCode = error.response?.statusCode;
if (statusCode != null) {
final status = HttpStatus.fromCode(statusCode);
// 显示用户友好的错误信息
showToast('请求失败: ${status.name}');
}
return handler.next(error);
},
));
}
虽然http_status覆盖了标准状态码,但实际项目中可能会遇到非标准状态码。这时可以通过扩展来增强功能:
dart复制extension CustomHttpStatus on HttpStatus {
static const int customError = 600;
static bool isCustomError(int code) {
return code == customError;
}
static HttpStatus fromCustomCode(int code) {
if (code == customError) {
return HttpStatus(
code: customError,
name: 'Custom Error',
description: '自定义错误状态码',
);
}
return HttpStatus.fromCode(code);
}
}
dart复制void handleResponse(Response response) {
final status = CustomHttpStatus.fromCustomCode(response.statusCode);
if (status.code == CustomHttpStatus.customError) {
// 处理自定义错误
} else if (HttpStatus.isServerError(status.code)) {
// 处理服务器错误
}
// 其他处理...
}
http_status是一个纯Dart实现的库,不包含任何原生代码,因此在鸿蒙平台上:
如果项目中同时使用了dart:io的HttpStatus,可以通过以下方式解决冲突:
dart复制import 'package:http_status/http_status.dart' as http_status;
// 使用时加上前缀
if (code == http_status.HttpStatus.ok) {
// ...
}
dart复制bool isValidStatusCode(int code) {
return code >= 100 && code < 600;
}
void safeHandleResponse(Response response) {
if (!isValidStatusCode(response.statusCode)) {
throw Exception('无效的状态码: ${response.statusCode}');
}
// 正常处理...
}
dart复制class ApiResponse<T> {
final int code;
final String message;
final T? data;
ApiResponse({
required this.code,
required this.message,
this.data,
});
factory ApiResponse.fromHttpResponse(Response response) {
final status = HttpStatus.fromCode(response.statusCode);
return ApiResponse(
code: status.code,
message: status.name,
data: response.data,
);
}
bool get isSuccess => HttpStatus.isSuccess(code);
}
dart复制Future<void> fetchData() async {
try {
final response = await dio.get('/api/data');
final apiResponse = ApiResponse.fromHttpResponse(response);
if (apiResponse.isSuccess) {
// 更新UI显示数据
} else {
// 显示错误信息
showErrorDialog(apiResponse.message);
}
} on DioError catch (e) {
final statusCode = e.response?.statusCode ?? 500;
final status = HttpStatus.fromCode(statusCode);
showErrorDialog(status.name);
}
}
dart复制void main() {
test('should correctly identify success status', () {
expect(HttpStatus.isSuccess(200), isTrue);
expect(HttpStatus.isSuccess(404), isFalse);
});
test('should handle custom status codes', () {
expect(CustomHttpStatus.isCustomError(600), isTrue);
});
}
http_status处理状态码,转换为业务模型dart复制String getLocalizedErrorMessage(HttpStatus status) {
switch (status.code) {
case HttpStatus.unauthorized.code:
return '请重新登录';
case HttpStatus.notFound.code:
return '资源不存在';
// 其他状态码的本地化...
default:
return status.name;
}
}
dart复制void trackStatusCode(HttpStatus status) {
analytics.logEvent('http_status', {
'code': status.code,
'name': status.name,
'timestamp': DateTime.now().millisecondsSinceEpoch,
});
}
在实际项目中采用http_status后,我们的代码质量得到了显著提升。最明显的变化是代码审查时不再需要解释各种数字的含义,新成员也能快速理解网络层的处理逻辑。特别是在处理复杂业务流时,语义化的状态码让条件判断变得一目了然。