所需依赖添加在项目中的pubspec.yaml中:
dio: ^4.0.6 #网络请求 connectivity_plus: ^2.3.6 #网络监测 pretty_dio_logger: ^1.1.1 #日志打印
class HttpRequest { // 单例模式使用Http类, static final HttpRequest _instance = HttpRequest._internal(); factory HttpRequest() => _instance; static late final Dio dio; /// 内部构造方法 HttpRequest._internal() { /// 初始化dio BaseOptions options = BaseOptions( connectTimeout: HttpOptions.connectTimeout, receiveTimeout: HttpOptions.receiveTimeout, sendTimeout: HttpOptions.sendTimeout, baseUrl: HttpOptions.baseUrl); dio = Dio(options); /// 添加各种拦截器 dio.interceptors.add(ErrorInterceptor()); dio.interceptors.add(PrettyDioLogger( requestHeader: true, requestBody: true, responseHeader: true, responseBody: true)); } /// 封装request方法 Future request({ required String path, required HttpMethod method, dynamic data, Map<String, dynamic>? queryParameters, bool showLoading = true, bool showErrorMessage = true, }) async { const Map methodValues = { HttpMethod.get: 'get', HttpMethod.post: 'post', HttpMethod.put: 'put', HttpMethod.delete: 'delete', HttpMethod.patch: 'patch', HttpMethod.head: 'head' }; //动态添加header头 Map<String, dynamic> headers = Map<String, dynamic>(); headers["version"] = "1.0.0"; Options options = Options( method: methodValues[method], headers: headers, ); try { if (showLoading) { EasyLoading.show(status: 'loading...'); } Response response = await HttpRequest.dio.request( path, data: data, queryParameters: queryParameters, options: options, ); return response.data; } on DioError catch (error) { HttpException httpException = error.error; if (showErrorMessage) { EasyLoading.showToast(httpException.msg); } } finally { if (showLoading) { EasyLoading.dismiss(); } } } } enum HttpMethod { get, post, delete, put, patch, head, }
class ErrorInterceptor extends Interceptor { @override void onError(DioError err, ErrorInterceptorHandler handler) async { /// 根据DioError创建HttpException HttpException httpException = HttpException.create(err); /// dio默认的错误实例,如果是没有网络,只能得到一个未知错误,无法精准的得知是否是无网络的情况 /// 这里对于断网的情况,给一个特殊的code和msg if (err.type == DioErrorType.other) { var connectivityResult = await (Connectivity().checkConnectivity()); if (connectivityResult == ConnectivityResult.none) { httpException = HttpException(code: -100, msg: 'None Network.'); } } /// 将自定义的HttpException err.error = httpException; /// 调用父类,回到dio框架 super.onError(err, handler); } }
class HttpException implements Exception { final int code; final String msg; HttpException({ this.code = -1, this.msg = 'unknow error', }); @override String toString() { return 'Http Error [$code]: $msg'; } factory HttpException.create(DioError error) { /// dio异常 switch (error.type) { case DioErrorType.cancel: { return HttpException(code: -1, msg: 'request cancel'); } case DioErrorType.connectTimeout: { return HttpException(code: -1, msg: 'connect timeout'); } case DioErrorType.sendTimeout: { return HttpException(code: -1, msg: 'send timeout'); } case DioErrorType.receiveTimeout: { return HttpException(code: -1, msg: 'receive timeout'); } case DioErrorType.response: { try { int statusCode = error.response?.statusCode ?? 0; // String errMsg = error.response.statusMessage; // return ErrorEntity(code: errCode, message: errMsg); switch (statusCode) { case 400: { return HttpException(code: statusCode, msg: 'Request syntax error'); } case 401: { return HttpException(code: statusCode, msg: 'Without permission'); } case 403: { return HttpException(code: statusCode, msg: 'Server rejects execution'); } case 404: { return HttpException(code: statusCode, msg: 'Unable to connect to server'); } case 405: { return HttpException(code: statusCode, msg: 'The request method is disabled'); } case 500: { return HttpException(code: statusCode, msg: 'Server internal error'); } case 502: { return HttpException(code: statusCode, msg: 'Invalid request'); } case 503: { return HttpException(code: statusCode, msg: 'The server is down.'); } case 505: { return HttpException(code: statusCode, msg: 'HTTP requests are not supported'); } default: { return HttpException( code: statusCode, msg: error.response?.statusMessage ?? 'unknow error'); } } } on Exception catch (_) { return HttpException(code: -1, msg: 'unknow error'); } } default: { return HttpException(code: -1, msg: error.message); } } } }
class HttpOptions { /// 超时时间;单位是ms static const int connectTimeout = 15000; static const int receiveTimeout = 15000; static const int sendTimeout = 15000; /// 地址域名前缀 static const String baseUrl = '************'; }
/// 调用底层的request,重新提供get,post等方便方法 class HttpUtils { static HttpRequest httpRequest = HttpRequest(); /// get static Future get({ required String path, Map<String, dynamic>? queryParameters, bool showLoading = true, bool showErrorMessage = true, }) { return httpRequest.request( path: path, method: HttpMethod.get, queryParameters: queryParameters, showLoading: showLoading, showErrorMessage: showErrorMessage, ); } /// post static Future post({ required String path, required HttpMethod method, dynamic data, bool showLoading = true, bool showErrorMessage = true, }) { return httpRequest.request( path: path, method: HttpMethod.post, data: data, showLoading: showLoading, showErrorMessage: showErrorMessage, ); } }