http_provider.dart 11 KB

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