Flutter Deer网络请求封装:基于Dio的高效数据交互方案

【免费下载链接】flutter_deer 🦌 Flutter 练习项目(包括集成测试、可访问性测试)。内含完整UI设计图,更贴近真实项目的练习。Flutter practice project (including integration testing and accessibility testing). Contains complete UI design drawings for a more realistic practice project. 【免费下载链接】flutter_deer 项目地址: https://gitcode.com/gh_mirrors/fl/flutter_deer

在移动应用开发中,网络请求是连接前端与后端的核心桥梁。一个健壮、可扩展的网络请求架构能够显著提升开发效率并改善用户体验。Flutter Deer项目作为一个完整的Flutter练习项目,其网络层基于Dio实现了一套高效的数据交互方案,涵盖了请求配置、拦截器处理、错误统一管理等关键功能。本文将深入剖析这一实现方案,帮助开发者理解如何在实际项目中构建可靠的网络请求模块。

网络架构概览

Flutter Deer的网络模块采用分层设计,主要包含请求配置、拦截器链、数据解析和错误处理四个核心部分。这一架构确保了代码的可维护性和可扩展性,同时提供了一致的API调用体验。

网络模块的核心代码集中在lib/net/目录下,主要文件包括:

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的网络模块还包含多项性能优化措施:

  1. 数据解析优化:根据数据大小自动选择是否使用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);
  1. 请求取消:支持通过CancelToken取消正在进行的请求,特别适用于页面销毁时取消未完成的请求,避免内存泄漏:
void _cancelLogPrint(dynamic e, String url) {
  if (e is DioException && CancelToken.isCancel(e)) {
    Log.e('取消请求接口: $url');
  }
}
  1. 统一数据模型:通过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应用中构建健壮、高效的网络层,为开发者提供了宝贵的参考。无论是初学者还是有经验的开发者,都能从中学习到网络请求封装的精髓,提升自己的项目开发能力。

网络请求架构图

【免费下载链接】flutter_deer 🦌 Flutter 练习项目(包括集成测试、可访问性测试)。内含完整UI设计图,更贴近真实项目的练习。Flutter practice project (including integration testing and accessibility testing). Contains complete UI design drawings for a more realistic practice project. 【免费下载链接】flutter_deer 项目地址: https://gitcode.com/gh_mirrors/fl/flutter_deer

Logo

开源鸿蒙跨平台开发社区汇聚开发者与厂商,共建“一次开发,多端部署”的开源生态,致力于降低跨端开发门槛,推动万物智联创新。

更多推荐