flutter封装的dio网络请求

实际项目里用到的对dio的封装,稳定运行很久 满足你的各种需求
用法如下,可以支持toast以及网络请求中是否有loading框
最后面有demo地址,你可以直接拿来用

  Map map = await JDApiRequest.post('xxxx')
          .params({'action': 'register', 'mobile': ''1234324341})
          .needToastError(true)
          .needLoading(true)
          .request;


enum JDRequestMethod {
  get,
  post, // 默认 json 格式
  postWithFormData,
}

typedef OnRequestStart = Function(String requestTag);
typedef OnRequestSuccess = Function(String requestTag);
typedef OnRequestFail = Function(
    String requestTag, Object exception, StackTrace stackTrace);

class JDRequestModel {
  final String code;
  final String msg;
  final dynamic data;

  JDRequestModel(this.code, this.msg, this.data);
}

@immutable
class JDRequestListener {
  /// 请求开始
  final OnRequestStart? onRequestStart;

  /// 请求成功
  final OnRequestSuccess? onRequestSuccess;

  /// 请求失败
  final OnRequestFail? onRequestFail;

  /// [toString]输出的文字
  final String? toStringText;

  const JDRequestListener(
      {this.onRequestStart,
      this.onRequestSuccess,
      this.onRequestFail,
      this.toStringText});

  @override
  String toString() => toStringText ?? super.toString();
}

typedef HookApiServiceHeaders = Map<String, dynamic> Function();

class JDApiRequest {
  static HookApiServiceHeaders? httpHeaders;
  static late String apiServiceUrl;

  final String _url;
  final JDRequestMethod _method;
  Map<String, dynamic>? requestParams;

  // 超时时间
  int? timeOutSecond;

  bool _needToast = false;
  bool _needFilterRequest = true;
  String? _requestTag;
  CancelToken? _cancelToken;
  JDRequestListener? _loadListener;

  /// 请求工具
  JDApiRequest._(this._method, this._url);

  /// GET 请求
  factory JDApiRequest.get(String url) =>
      JDApiRequest._(JDRequestMethod.get, url);

  /// POST 请求
  factory JDApiRequest.post(String url) =>
      JDApiRequest._(JDRequestMethod.post, url);

  /// POST 请求 通过 表单
  factory JDApiRequest.postFormData(String url) =>
      JDApiRequest._(JDRequestMethod.postWithFormData, url);

  /// 携带的参数
  JDApiRequest params(Map<String, dynamic>? params) {
    try {
      requestParams = params;
    } catch (error) {
      TDToast.showDebug('赋值失败($_url),请检查log');
    }
    return this;
  }

  /// 指定的请求[tag] 等于空串时不输出请求日志
  /// 需配合[needFilterRequest]一起使用
  JDApiRequest tag(String tag) {
    _requestTag = tag;
    return this;
  }

  JDApiRequest setTimeOut(int time) {
    timeOutSecond = time;
    return this;
  }

  /// 请求失败时是否通过toast提示
  JDApiRequest needToastError(bool need) {
    _needToast = need;
    return this;
  }

  /// 需要过滤请求,默认true,设置为false不参与过滤
  JDApiRequest needFilterRequest(bool need) {
    _needFilterRequest = need;
    return this;
  }

  /// 设置加载回调
  JDApiRequest loadListener(JDRequestListener? loadListener) {
    _loadListener = loadListener;
    return this;
  }

  JDApiRequest needLoading(bool needLoading) {
    if (needLoading) {
      _loadListener = JDApiRequest.defaultListener;
    }
    return this;
  }

  /// 设置取消的token
  JDApiRequest cancelToken(CancelToken? cancelToken) {
    _cancelToken = cancelToken;
    return this;
  }

  /// 发起请求
  Future<Map<String, dynamic>> get request => _startRequest(this);

  /// 生成请求Tag
  static String _generateRequestTag(JDApiRequest request) {
    final requestTime = DateTime.now().millisecondsSinceEpoch / 1000;
    if (request._method == JDRequestMethod.get) {
      return json.encode({
        'method': 'GET',
        'url': request._url,
        'params': request.requestParams,
        'requestTime': requestTime
      });
    } else if (request._method == JDRequestMethod.post) {
      return json.encode({
        'method': 'POST',
        'url': request._url,
        'params': request.requestParams,
        'requestTime': requestTime
      });
    } else if (request._method == JDRequestMethod.postWithFormData) {
      return json.encode({
        'method': 'POST_WITH_FORM_DATA',
        'url': request._url,
        'params': null,
        'requestTime': requestTime
      });
    }
    return request.hashCode.toString();
  }

  /// 生成请求路径
  static String _generateRequestUrl(JDApiRequest request) {
    if (request._url.startsWith(r'http://') == true ||
        request._url.startsWith(r'https://') == true) {
      return request._url;
    } else {
      return "${JDApiRequest.apiServiceUrl}${request._url}";
    }
  }

  /// 生成请求配置
  static Future<Map<String, dynamic>> _generateRequestParams(
      JDApiRequest request) async {
    Map<String, dynamic> baseMap =
        AppInitConfig.instance.requestParam.getRequestMap();
    // tdLog('请求参数11  $baseMap');
    baseMap.addAll(request.requestParams ?? {});
    // tdLog('请求参数22  $baseMap');
    return baseMap;
  }

  /// 生成请求配置
  static Options _generateRequestOption(JDApiRequest request) {
    JDRequestMethod method = request._method;
    String contentType;
    if (JDRequestMethod.post == method) {
      contentType = ContentType.json.toString();
    } else if (JDRequestMethod.postWithFormData == method) {
      contentType = ContentType('multipart', 'form-data').toString();
    } else {
      contentType = ContentType.binary.toString();
    }
    int timeOut = request.timeOutSecond ?? 7;
    Options options =
        Options(method: JDRequestMethod.get == method ? "GET" : "POST")
          ..headers = {
            ...?httpHeaders?.call(),
            HttpHeaders.acceptHeader: '*/*',
            HttpHeaders.contentTypeHeader: contentType,
          }
          ..sendTimeout = Duration(seconds: timeOut)
          ..receiveTimeout = Duration(seconds: timeOut);
    return options;
  }

  static get defaultListener {
    return JDRequestListener(
      onRequestStart: (String requestTag) {
        return JDLoadingTool.showLoading(tag: requestTag);
      },
      onRequestSuccess: (String requestTag) {
        return JDLoadingTool.dismissLoading(tag: requestTag);
      },
      onRequestFail:
          (String requestTag, Object exception, StackTrace stackTrace) {
        return JDLoadingTool.dismissLoading(tag: requestTag);
      },
      toStringText: 'defaultListener',
    );
  }
}

final Set<String?> _requestingList = {};

class TDDioInstance {
  Dio dio = Dio();
  factory TDDioInstance() => _instance;
  static final TDDioInstance _instance = TDDioInstance._internal();
  TDDioInstance._internal();
}

/// 开始请求
Future<Map<String, dynamic>> _startRequest(JDApiRequest request) async {
  final requestTag =
      request._requestTag ?? JDApiRequest._generateRequestTag(request);
  if (_requestingList.contains(requestTag) && request._needFilterRequest) {
    jdLog("重复请求中($request)..");
  }
  final startTime = DateTime.now();
  try {
    _requestingList.add(requestTag);
    _runZonedIfNotNull(request._loadListener?.onRequestStart?.call(requestTag));
    final resp = await _requestInner(request, requestTag);
    _runZonedIfNotNull(
        request._loadListener?.onRequestSuccess?.call(requestTag));
    jdLog("请求成功结束----->  ${request._url} $resp");
    if (!resp.responseSucceed()) {
      if (request._needToast) {
        TDToast.showToast(resp.getStringNotNull(TDResponseConstant.message));
      }
    }
    return Future.value(resp);
  } catch (exception, stackTrace) {
    String errorMsg = '';
    int errorCode = 0;
    if (exception is JDApiException) {
      errorMsg = exception.msg;
      errorCode = exception.code;
      jdLog(
          '请求异常1:error--->  ${exception.msg} requestTag--> $requestTag stackTrace---> ${stackTrace.toString()}');
      if (request._needToast) {
        TDToast.showToast(exception.msg);
      }
    } else {
      jdLog('请求异常2---> ${exception.toString()}');
      errorMsg = exception.toString();
      errorCode = -101;
      if (request._needToast) {
        TDToast.showToast(errorMsg);
      }
    }
    _runZonedIfNotNull(request._loadListener?.onRequestFail
        ?.call(requestTag, exception, stackTrace));
    return {
      'error': {'errorMsg': errorMsg, 'errorCode': errorCode}
    };
  } finally {
    _requestingList.remove(requestTag);
    final duration = DateTime.now().duration - startTime.duration;
    if (duration > const Duration(seconds: 3)) {
      // TDLoggerUtil.e('接口请求时间过长:[tag: $requestTag, duration: $duration]');
    }
  }
}

/// 解析响应
Future<Map<String, dynamic>> _requestInner(
    JDApiRequest request, String requestTagOnce) async {
  try {
    // String requestShortTag = shortHash(requestTagOnce);
    String requestFullUrl = JDApiRequest._generateRequestUrl(request);
    Map<String, dynamic> params =
        await JDApiRequest._generateRequestParams(request);
    Options option = JDApiRequest._generateRequestOption(request);

    jdLog('开始请求requestUrl----->  ${request._url} 参数-->  $params');

    Response response = await TDDioInstance().dio.request(
          requestFullUrl,
          queryParameters:
              request._method == JDRequestMethod.get ? params : null,
          data: request._method == JDRequestMethod.postWithFormData ||
                  request._method == JDRequestMethod.post
              ? FormData.fromMap(params)
              : params,
          options: option,
          cancelToken: request._cancelToken,
        );
    Map<String, dynamic> responseMap = {};
    dynamic responseData = response.data;
    if (responseData is String) {
      responseData = json.decode(responseData);
    }
    responseMap = responseData;

    return responseMap;
  } on JDApiException {
    rethrow;
  } on DioException catch (exception) {
    if (kDebugMode) {
      throw ApiNetworkException(exception.response?.statusCode ?? -1,
          '${exception.message}', request, exception);
    } else {
      throw ApiNetworkException(exception.response?.statusCode ?? -1,
          '连接服务器失败,请检查网络~', request, exception);
    }
  } catch (exception) {
    if (kDebugMode) {
      throw JDApiException(
          -101, '系统出现未知错误\n(${exception.toString()})', request, exception);
    } else {
      throw JDApiException(-101, '系统出现未知错误', request, exception);
    }
  }
}

_runZonedIfNotNull<R>(R Function()? body) {
  if (body != null) runZoned(body);
}


具体的封装实现在https://gitee.com/kuaipai/my_app.git

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

推荐阅读更多精彩内容