Flutter Deer网络请求封装:基于Dio的高效数据交互方案
在移动应用开发中,网络请求是连接前端与后端的核心桥梁。一个健壮、可扩展的网络请求架构能够显著提升开发效率并改善用户体验。Flutter Deer项目作为一个完整的Flutter练习项目,其网络层基于Dio实现了一套高效的数据交互方案,涵盖了请求配置、拦截器处理、错误统一管理等关键功能。本文将深入剖析这一实现方案,帮助开发者理解如何在实际项目中构建可靠的网络请求模块。## 网络架构概览Flu...
Flutter Deer网络请求封装:基于Dio的高效数据交互方案
在移动应用开发中,网络请求是连接前端与后端的核心桥梁。一个健壮、可扩展的网络请求架构能够显著提升开发效率并改善用户体验。Flutter Deer项目作为一个完整的Flutter练习项目,其网络层基于Dio实现了一套高效的数据交互方案,涵盖了请求配置、拦截器处理、错误统一管理等关键功能。本文将深入剖析这一实现方案,帮助开发者理解如何在实际项目中构建可靠的网络请求模块。
网络架构概览
Flutter Deer的网络模块采用分层设计,主要包含请求配置、拦截器链、数据解析和错误处理四个核心部分。这一架构确保了代码的可维护性和可扩展性,同时提供了一致的API调用体验。
网络模块的核心代码集中在lib/net/目录下,主要文件包括:
- 请求工具类:dio_utils.dart
- 拦截器实现:intercept.dart
- 错误处理:error_handle.dart
- 基础数据模型:base_entity.dart
Dio工具类设计
DioUtils作为网络请求的入口类,采用单例模式设计,确保全局只有一个Dio实例在运行。这种设计不仅节省资源,还能保证拦截器和配置的一致性。
初始化配置
DioUtils的初始化过程中,通过configDio方法可以灵活配置超时时间、基础URL和拦截器等参数:
void configDio({
Duration? connectTimeout,
Duration? receiveTimeout,
Duration? sendTimeout,
String? baseUrl,
List<Interceptor>? interceptors,
}) {
_connectTimeout = connectTimeout ?? _connectTimeout;
_receiveTimeout = receiveTimeout ?? _receiveTimeout;
_sendTimeout = sendTimeout ?? _sendTimeout;
_baseUrl = baseUrl ?? _baseUrl;
_interceptors = interceptors ?? _interceptors;
}
请求方法封装
DioUtils封装了get、post等常见HTTP方法,通过requestNetwork方法提供统一的请求入口。该方法支持泛型参数,能够自动将JSON响应转换为指定类型的对象:
Future<dynamic> requestNetwork<T>(Method method, String url, {
NetSuccessCallback<T?>? onSuccess,
NetErrorCallback? onError,
Object? params,
Map<String, dynamic>? queryParameters,
CancelToken? cancelToken,
Options? options,
}) {
return _request<T>(method.value, url,
data: params,
queryParameters: queryParameters,
options: options,
cancelToken: cancelToken,
).then<void>((BaseEntity<T> result) {
if (result.code == 0) {
onSuccess?.call(result.data);
} else {
_onError(result.code, result.message, onError);
}
}, onError: (dynamic e) {
_cancelLogPrint(e, url);
final NetError error = ExceptionHandle.handleException(e);
_onError(error.code, error.msg, onError);
});
}
拦截器链实现
拦截器是Dio的核心特性之一,Flutter Deer项目通过组合多个拦截器实现了认证、Token刷新、日志记录和数据适配等功能。
认证拦截器
AuthInterceptor负责在请求头中添加认证Token,确保API调用的安全性:
class AuthInterceptor extends Interceptor {
@override
void onRequest(RequestOptions options, RequestInterceptorHandler handler) {
final String accessToken = SpUtil.getString(Constant.accessToken).nullSafe;
if (accessToken.isNotEmpty) {
options.headers['Authorization'] = 'token $accessToken';
}
super.onRequest(options, handler);
}
}
Token刷新拦截器
TokenInterceptor实现了Token过期自动刷新的功能,当收到401响应时,它会自动获取新的Token并重试失败的请求:
@override
Future<void> onResponse(Response<dynamic> response, ResponseInterceptorHandler handler) async {
//401代表token过期
if (response.statusCode == ExceptionHandle.unauthorized) {
Log.d('-----------自动刷新Token------------');
final String? accessToken = await getToken(); // 获取新的accessToken
Log.e('-----------NewToken: $accessToken ------------');
SpUtil.putString(Constant.accessToken, accessToken.nullSafe);
if (accessToken != null) {
// 重新请求失败接口
final RequestOptions request = response.requestOptions;
request.headers['Authorization'] = 'Bearer $accessToken';
// ... 重新请求逻辑
}
}
super.onResponse(response, handler);
}
日志拦截器
LoggingInterceptor用于记录请求和响应的详细信息,方便开发调试:
@override
void onRequest(RequestOptions options, RequestInterceptorHandler handler) {
_startTime = DateTime.now();
Log.d('----------Start----------');
Log.d('RequestUrl: ${options.baseUrl}${options.path}');
Log.d('RequestMethod: ${options.method}');
Log.d('RequestHeaders:${options.headers}');
Log.d('RequestData: ${options.data}');
super.onRequest(options, handler);
}
数据适配拦截器
AdapterInterceptor负责将不同格式的API响应统一转换为项目内部使用的数据格式,简化后续的解析过程:
Response<dynamic> adapterData(Response<dynamic> response) {
String result;
String content = response.data?.toString() ?? '';
/// 成功时,直接格式化返回
if (response.statusCode == ExceptionHandle.success || response.statusCode == ExceptionHandle.success_not_content) {
if (content.isEmpty) {
content = _kDefaultText;
}
result = sprintf(_kSuccessFormat, [content]);
response.statusCode = ExceptionHandle.success;
} else {
// ... 错误处理逻辑
}
response.data = result;
return response;
}
错误处理机制
Flutter Deer的网络模块采用集中式错误处理机制,通过ExceptionHandle类统一管理错误码和错误信息:
class ExceptionHandle {
static const int success = 200;
static const int success_not_content = 204;
static const int unauthorized = 401;
static const int not_found = 404;
static const int unknown_error = 1000;
static const int parse_error = 1001;
static const int network_error = 1002;
// ... 其他错误码定义
static NetError handleException(dynamic e) {
if (e is DioException) {
if (e.type == DioExceptionType.connectionTimeout) {
return NetError(network_error, "网络连接超时,请检查网络设置");
}
// ... 其他Dio错误处理
}
return NetError(unknown_error, "未知异常");
}
}
实际应用示例
以下是一个使用Flutter Deer网络模块获取商品列表的示例:
void fetchGoodsList() {
DioUtils.instance.requestNetwork<List<Goods>>(
Method.get,
"goods/list",
onSuccess: (data) {
// 处理成功响应
setState(() {
goodsList = data;
});
},
onError: (code, msg) {
// 处理错误
ToastUtils.show(msg);
},
);
}
性能优化策略
Flutter Deer的网络模块还包含多项性能优化措施:
- 数据解析优化:根据数据大小自动选择是否使用compute isolate进行JSON解析,避免阻塞UI线程:
final bool isCompute = !Constant.isDriverTest && data.length > 10 * 1024;
debugPrint('isCompute:$isCompute');
final Map<String, dynamic> map = isCompute ? await compute(parseData, data) : parseData(data);
- 请求取消:支持通过CancelToken取消正在进行的请求,特别适用于页面销毁时取消未完成的请求,避免内存泄漏:
void _cancelLogPrint(dynamic e, String url) {
if (e is DioException && CancelToken.isCancel(e)) {
Log.e('取消请求接口: $url');
}
}
- 统一数据模型:通过BaseEntity统一封装API响应,简化数据处理逻辑:
class BaseEntity<T> {
int code;
String message;
T? data;
BaseEntity({required this.code, required this.message, this.data});
factory BaseEntity.fromJson(Map<String, dynamic> json) {
return BaseEntity(
code: json['code'],
message: json['message'],
data: json['data'],
);
}
}
总结
Flutter Deer的网络请求封装基于Dio构建了一套完整、高效的数据交互方案。通过单例模式的Dio工具类、灵活的拦截器链、集中式错误处理和性能优化策略,它为移动应用开发提供了可靠的网络层支持。无论是小型项目还是大型应用,这一方案都能够满足复杂的网络请求需求,同时保持代码的可维护性和可扩展性。
项目的测试用例展示了网络模块的可靠性:test/net/dio_test.dart。开发者可以通过这些测试了解网络模块的各种边界情况处理,进一步完善自己的项目。
Flutter Deer项目的网络模块不仅是一个功能实现,更是一套最佳实践的集合。它展示了如何在Flutter应用中构建健壮、高效的网络层,为开发者提供了宝贵的参考。无论是初学者还是有经验的开发者,都能从中学习到网络请求封装的精髓,提升自己的项目开发能力。
更多推荐





所有评论(0)