import 'dart:convert'; import 'dart:developer'; import 'dart:ui'; import 'package:dio/dio.dart'; import 'package:flutter_easyloading/flutter_easyloading.dart'; import '../utils/toast_utils.dart'; ///请求方式-枚举类型 enum MethodType { get, post, delete, put, patch } class HttpUtils { static final HttpUtils _instance = HttpUtils._internal(baseUrl: ''); factory HttpUtils() => _instance; late Dio dio; HttpUtils._internal({required String baseUrl}) { BaseOptions options = BaseOptions( baseUrl: baseUrl, contentType: 'application/json; charset=utf-8', connectTimeout: const Duration(milliseconds: 15000), receiveTimeout: const Duration(milliseconds: 15000), responseType: ResponseType.json, validateStatus: (status) { return true; }, ); dio = Dio(options); /// 添加请求日志 dio.interceptors.add(LogInterceptor( requestBody: true, responseHeader: false, responseBody: false, error: false, )); /// 添加拦截器 dio.interceptors.add(InterceptorsWrapper( onResponse: (response, handler) { /// 打印返回值 const bool inProduction = bool.fromEnvironment("dart.vm.product"); if (!inProduction) { log( jsonEncode(response.data), name: 'Response Text: ', ); } /// 对接口抛出异常的检查 _apiVerify(response); return handler.next(response); }, )); } ///统一请求入口 static Future request( String baseUrl, String path, { String? token, MethodType method = MethodType.get, Map? headers, Map? body, Map? queryParameters, bool isShowLoading = false, CancelToken? cancelToken, VoidCallback? unLoginAction, }) async { ///开始网络请求 late NetResult netResult; Dio dio = HttpUtils._internal(baseUrl: baseUrl).dio; // String? token1 = token ?? ''; Map headerMap = {}; if (headers != null) headerMap.addAll(headers); headerMap['token'] = token; headerMap['Authorization'] = token; Options options = Options( method: method.name, headers: headerMap, ); CancelToken newCancelToken = cancelToken ?? CancelToken(); try { if (isShowLoading) { await EasyLoading.show( // status: 'loading...', maskType: EasyLoadingMaskType.black, ); } final response = await dio.request( path, options: options, queryParameters: queryParameters, data: body, cancelToken: newCancelToken, ); // if (response.headers["authorization"] != null) { // LocalStore.setValue( // key: StoreValue.tokenKey, // value: response.headers["authorization"]![0]); // } if (isShowLoading) EasyLoading.dismiss(); netResult = NetResult( headers: response.headers, result: response.data, statusCode: response.statusCode ?? 0, error: _apiIsSucceed(response), ); } on DioError catch (error) { if (isShowLoading) EasyLoading.dismiss(); _formatError(error); netResult = NetResult( errorMeg: error.message ?? '服务器出现错误', ); } return netResult; } ///下载 static Future download( String path, String savePath, { ProgressCallback? onReceiveProgress, Map? queryParameters, CancelToken? cancelToken, bool deleteOnError = true, String lengthHeader = Headers.contentLengthHeader, data, Options? options, }) async { ///开始网络请求 late NetResult netResult; try { Response response = await Dio().download( path, savePath, onReceiveProgress: onReceiveProgress, queryParameters: queryParameters, cancelToken: cancelToken, deleteOnError: deleteOnError, lengthHeader: lengthHeader, data: data, options: options, ); netResult = NetResult( headers: response.headers, result: 'Download successful', statusCode: response.statusCode ?? 0, error: response.statusCode != 200, ); } on DioError catch (error) { _formatError(error); netResult = NetResult( errorMeg: error.message ?? '服务器出现错误', result: 'Download failure', ); } return netResult; } ///判断接口是否成功 static bool _apiIsSucceed(Response response) { if (response.data != null && response.data != '') { Map map = response.data; return map['resultCode'] == 'OK' ? false : true; } return false; } ///接口校验 static void _apiVerify(Response response, {VoidCallback? unLoginAction}) { if (response.data != null && response.data != '') { ///判断返回值是否是Map if (response.data is Map) { Map map = response.data; String resultCode = map['resultCode']; if (resultCode.toUpperCase() == "FAIL") { throw DioException( requestOptions: RequestOptions(path: ''), response: response, type: DioExceptionType.unknown, error: response.data, message: map['resultMsg'], ); } if (resultCode.toUpperCase() == "UNLOGIN") { unLoginAction?.call(); return; } } else if (response.data is String) { throw DioException( requestOptions: RequestOptions(path: ''), response: response, type: DioExceptionType.unknown, error: response.data, message: response.data, ); } } else { throw DioException( requestOptions: RequestOptions(path: ''), response: response, type: DioExceptionType.unknown, error: response.data, message: response.data, ); } } /* * Dio库error统一处理 */ static void _formatError(DioException error) { switch (error.type) { case DioExceptionType.cancel: break; case DioExceptionType.connectionTimeout: ToastUtils.showToast(msg: '网络连接超时'); break; case DioExceptionType.sendTimeout: ToastUtils.showToast(msg: '网络请求超时'); break; case DioExceptionType.receiveTimeout: ToastUtils.showToast(msg: '服务响应超时'); break; case DioExceptionType.unknown: ToastUtils.showToast(msg: error.message); break; case DioExceptionType.badResponse: try { int? errCode = error.response!.statusCode; String? errMsg = error.response!.statusMessage; switch (errCode) { case 400: ToastUtils.errorToast(errorText: '请求语法错误'); break; case 401: ToastUtils.errorToast(errorText: '没有权限'); break; case 403: ToastUtils.errorToast(errorText: '服务器拒绝执行'); break; case 404: ToastUtils.errorToast(errorText: '无法连接服务器'); break; case 405: ToastUtils.errorToast(errorText: '请求方法被禁止'); break; case 500: ToastUtils.errorToast(errorText: '服务器出现问题'); break; case 502: ToastUtils.errorToast(errorText: '无效的请求'); break; case 503: ToastUtils.errorToast(errorText: '服务器挂了'); break; case 505: ToastUtils.errorToast(errorText: '不支持HTTP协议请求'); break; default: ToastUtils.errorToast(errorText: errMsg ?? '未知错误'); break; } } on Exception catch (_) { ToastUtils.errorToast(errorText: '未知错误'); break; } break; default: ToastUtils.errorToast(errorText: error.message); break; } } } /// 自定义Dio返回类 class NetResult { dynamic result; dynamic headers; int total; bool error; int statusCode; String errorMeg; bool get success => !error; NetResult({ this.result, this.headers, this.statusCode = -1, this.error = true, this.total = 0, this.errorMeg = '', }); @override String toString() { return 'NetResult:statusCode: $statusCode \n' 'NetResult: headers: $headers \n' 'NetResult: error: $error \n' 'NetResult: total: $total \n' 'NetResult: errorMeg: $errorMeg \n' 'NetResult: result: ${result.toString()}'; } } /// 自定义Dio取消请求处理类 class CustomCancelToken { static CancelToken cancelToken = CancelToken(); static cancel() { cancelToken.cancel('取消请求'); cancelToken = CancelToken(); } }