http_provider.dart 10 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268
  1. import 'dart:async';
  2. import 'dart:typed_data';
  3. import 'package:dio/dio.dart';
  4. import 'package:flutter/foundation.dart';
  5. import 'package:shared/utils/log_utils.dart';
  6. import '../core/platform_config.dart';
  7. import '../engine/network/network_engine.dart';
  8. import 'http_result.dart';
  9. enum CacheControl {
  10. noCache, //不使用缓存
  11. onlyCache, //只用缓存
  12. cacheFirstOrNetworkPut, //有缓存先用缓存,没有缓存进行网络请求再存入缓存
  13. onlyNetworkPutCache, //只用网络请求,但是会存入缓存
  14. }
  15. // ignore: constant_identifier_names
  16. enum HttpMethod { GET, POST }
  17. ///Dio封装管理,网络请求引擎类
  18. class HttpProvider {
  19. late NetworkEngine networkEngine;
  20. //构造需要传递BaseUrl 和 需要添加的拦截器
  21. HttpProvider(String baseUrl, {List<Interceptor>? interceptors}) {
  22. //具体的执行网络请求逻辑在引擎类中
  23. networkEngine = NetworkEngine(baseUrl, interceptors);
  24. }
  25. /// 封装网络请求入口
  26. Future<HttpResult> requestNetResult(
  27. String url, {
  28. HttpMethod method = HttpMethod.GET, //指明Get还是Post请求
  29. Map<String, String>? headers, //请求头
  30. Map<String, dynamic>? params, //请求参数,Get的Params,Post的Form
  31. Map<String, String>? paths, //文件Flie
  32. Map<String, Uint8List>? pathStreams, //文件流
  33. CacheControl? cacheControl, // Get请求是否需要缓存
  34. Duration? cacheExpiration, //缓存是否需要过期时间,过期时间为多长时间
  35. ProgressCallback? send, // 上传进度监听
  36. ProgressCallback? receive, // 下载监听
  37. CancelToken? cancelToken, // 用于取消的 token,可以多个请求绑定一个 token
  38. bool networkDebounce = false, // 当前网络请求是否需要网络防抖去重
  39. bool isShowLoadingDialog = false, // 是否展示 Loading 弹框
  40. }) async {
  41. //尝试网络请求去重,内部逻辑判断发起真正的网络请求
  42. if (networkDebounce) {
  43. if (headers == null || headers.isEmpty) {
  44. headers = <String, String>{};
  45. }
  46. headers['network_debounce'] = "true";
  47. }
  48. if (isShowLoadingDialog) {
  49. if (headers == null || headers.isEmpty) {
  50. headers = <String, String>{};
  51. }
  52. headers['is_show_loading_dialog'] = "true";
  53. }
  54. return _executeRequests(
  55. url,
  56. method,
  57. headers,
  58. params,
  59. paths,
  60. pathStreams,
  61. cacheControl,
  62. cacheExpiration,
  63. send,
  64. receive,
  65. cancelToken,
  66. networkDebounce,
  67. );
  68. }
  69. /// 真正的执行请求,处理缓存与返回的结果
  70. Future<HttpResult> _executeRequests(
  71. String url, //请求地址
  72. HttpMethod method, //请求方式
  73. Map<String, String>? headers, //请求头
  74. Map<String, dynamic>? params, //请求参数
  75. Map<String, String>? paths, //文件
  76. Map<String, Uint8List>? pathStreams, //文件流
  77. CacheControl? cacheControl, //Get请求缓存控制
  78. Duration? cacheExpiration, //缓存文件有效时间
  79. ProgressCallback? send, // 上传进度监听
  80. ProgressCallback? receive, // 下载监听
  81. CancelToken? cancelToken, // 用于取消的 token,可以多个请求绑定一个 token
  82. bool networkDebounce, // 当前网络请求是否需要网络防抖去重
  83. ) async {
  84. try {
  85. //根据参数封装请求并开始请求
  86. Response response;
  87. // 定义一个局部函数,封装重复的请求逻辑
  88. Future<Response> executeGenerateRequest() async {
  89. return _generateRequest(
  90. method,
  91. params,
  92. paths,
  93. pathStreams,
  94. url,
  95. headers,
  96. cacheControl,
  97. cacheExpiration,
  98. send,
  99. receive,
  100. cancelToken,
  101. );
  102. }
  103. if (!kReleaseMode) {
  104. final startTime = DateTime.now();
  105. response = await executeGenerateRequest();
  106. final endTime = DateTime.now();
  107. final duration = endTime.difference(startTime).inMilliseconds;
  108. Log.d('网络请求耗时 $duration 毫秒,HttpCode:${response.statusCode} HttpMessage:${response.statusMessage} 响应内容 ${response.data}}');
  109. } else {
  110. response = await executeGenerateRequest();
  111. }
  112. //判断成功与失败, 200 成功 401 授权过期, 422 请求参数错误,429 请求校验不通过
  113. if (response.statusCode == 200 || response.statusCode == 401 || response.statusCode == 422 || response.statusCode == 429) {
  114. //网络请求完成之后获取正常的Json-Map
  115. Map<String, dynamic> jsonMap = response.data;
  116. //Http处理完了,现在处理 API 的 Code
  117. if (jsonMap.containsKey('code')) {
  118. int code = jsonMap['code'];
  119. // 如果有 code,并且 code = 200 说明成功
  120. if (code == 200) {
  121. if (jsonMap['data'] is List<dynamic>) {
  122. //成功->返回数组
  123. return HttpResult(
  124. isSuccess: true,
  125. code: code,
  126. msg: jsonMap['msg'],
  127. listJson: jsonMap['data'], //赋值给的 listJson 字段
  128. );
  129. } else {
  130. //成功->返回对象
  131. return HttpResult(
  132. isSuccess: true,
  133. code: code,
  134. msg: jsonMap['msg'],
  135. dataJson: jsonMap['data'], //赋值给的 dataJson 字段
  136. );
  137. }
  138. //如果code != 200 ,下面是错误的情况判断
  139. } else {
  140. if (jsonMap.containsKey('msg')) {
  141. //如果有msg字符串优先返回msg字符串
  142. return HttpResult(isSuccess: false, code: code, errorMsg: jsonMap['msg']);
  143. } else {
  144. //什么都没有就返回Http的错误字符串
  145. return HttpResult(isSuccess: false, code: code, errorMsg: jsonMap['message']);
  146. }
  147. }
  148. } else {
  149. //没有code,说明有错误信息,判断错误信息
  150. if (jsonMap.containsKey('msg')) {
  151. //如果有msg字符串优先返回msg字符串
  152. return HttpResult(isSuccess: false, errorMsg: jsonMap['msg']);
  153. } else {
  154. //什么都没有就返回Http的错误字符串
  155. return HttpResult(isSuccess: false, errorMsg: jsonMap['message']);
  156. }
  157. }
  158. } else {
  159. //返回Http的错误,给 Http Response 的 statusMessage 值
  160. return HttpResult(
  161. isSuccess: false,
  162. code: response.statusCode ?? PlatformConfig.networkDebounceCode,
  163. errorMsg: response.statusMessage,
  164. );
  165. }
  166. } on DioException catch (e) {
  167. Log.e("HttpProvider - DioException:$e 其他错误Error:${e.error.toString()}");
  168. if (e.response != null) {
  169. // 如果其他的Http网络请求的Code的处理
  170. Log.d("网络请求错误,data:${e.response?.data}");
  171. return HttpResult(isSuccess: false, errorMsg: "错误码:${e.response?.statusCode} 错误信息:${e.response?.statusMessage}");
  172. } else if (e.type == DioExceptionType.connectionTimeout ||
  173. e.type == DioExceptionType.sendTimeout ||
  174. e.type == DioExceptionType.receiveTimeout) {
  175. return HttpResult(isSuccess: false, errorMsg: "网络连接超时,请稍后再试");
  176. } else if (e.type == DioExceptionType.cancel) {
  177. return HttpResult(isSuccess: false, errorMsg: "网络请求已取消");
  178. } else if (e.type == DioExceptionType.badCertificate) {
  179. return HttpResult(isSuccess: false, errorMsg: "网络连接证书无效");
  180. } else if (e.type == DioExceptionType.badResponse) {
  181. return HttpResult(isSuccess: false, errorMsg: "网络响应错误,请稍后再试");
  182. } else if (e.type == DioExceptionType.connectionError) {
  183. return HttpResult(isSuccess: false, errorMsg: "网络连接错误,请检查网络连接");
  184. } else if (e.type == DioExceptionType.unknown) {
  185. //未知错误中尝试打印具体的错误信息
  186. if (e.error != null) {
  187. if (e.error.toString().contains("HandshakeException")) {
  188. return HttpResult(isSuccess: false, errorMsg: "网络连接错误,请检查网络连接");
  189. } else {
  190. return HttpResult(isSuccess: false, errorMsg: e.error.toString()); //这里打印的就是英文错误了,没有格式化
  191. }
  192. } else {
  193. return HttpResult(isSuccess: false, errorMsg: "网络请求出现未知错误");
  194. }
  195. } else {
  196. //如果有response走Api错误
  197. return HttpResult(isSuccess: false, errorMsg: e.message);
  198. }
  199. }
  200. }
  201. ///生成对应Get与Post的请求体,并封装对应的参数
  202. Future<Response> _generateRequest(
  203. HttpMethod? method,
  204. Map<String, dynamic>? params,
  205. Map<String, String>? paths, //文件
  206. Map<String, Uint8List>? pathStreams, //文件流
  207. String url,
  208. Map<String, String>? headers,
  209. CacheControl? cacheControl,
  210. Duration? cacheExpiration,
  211. ProgressCallback? send, // 上传进度监听
  212. ProgressCallback? receive, // 下载监听
  213. CancelToken? cancelToken, // 用于取消的 token,可以多个请求绑定一个 token
  214. ) async {
  215. if (method != null && method == HttpMethod.POST) {
  216. //以 Post 请求 FromData 的方式上传
  217. return networkEngine.executePost(
  218. url: url,
  219. params: params,
  220. paths: paths,
  221. pathStreams: pathStreams,
  222. headers: headers,
  223. send: send,
  224. receive: receive,
  225. cancelToken: cancelToken,
  226. );
  227. } else {
  228. //默认 Get 请求,添加逻辑是否需要处理缓存策略,具体缓存逻辑见拦截器
  229. if (cacheControl != null) {
  230. if (headers == null || headers.isEmpty) {
  231. headers = <String, String>{};
  232. }
  233. headers['cache_control'] = cacheControl.name;
  234. if (cacheExpiration != null) {
  235. headers['cache_expiration'] = cacheExpiration.inMilliseconds.toString();
  236. }
  237. }
  238. return networkEngine.executeGet(
  239. url: url,
  240. params: params,
  241. headers: headers,
  242. cacheControl: cacheControl,
  243. cacheExpiration: cacheExpiration,
  244. receive: receive,
  245. cancelToken: cancelToken,
  246. );
  247. }
  248. }
  249. }