http_provider.dart 10 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276
  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. if (e.response != null) {
  173. // 如果其他的Http网络请求的Code的处理
  174. Log.d("网络请求错误,data:${e.response?.data}");
  175. return HttpResult(isSuccess: false, errorMsg: "错误码:${e.response?.statusCode} 错误信息:${e.response?.statusMessage}");
  176. } else if (e.type == DioExceptionType.connectionTimeout || e.type == DioExceptionType.sendTimeout || e.type == DioExceptionType.receiveTimeout) {
  177. return HttpResult(isSuccess: false, errorMsg: "网络连接超时,请稍后再试");
  178. } else if (e.type == DioExceptionType.cancel) {
  179. return HttpResult(isSuccess: false, errorMsg: "网络请求已取消");
  180. } else if (e.type == DioExceptionType.badCertificate) {
  181. return HttpResult(isSuccess: false, errorMsg: "网络连接证书无效");
  182. } else if (e.type == DioExceptionType.badResponse) {
  183. return HttpResult(isSuccess: false, errorMsg: "网络响应错误,请稍后再试");
  184. } else if (e.type == DioExceptionType.connectionError) {
  185. return HttpResult(isSuccess: false, errorMsg: "网络连接错误,请检查网络连接");
  186. } else if (e.type == DioExceptionType.unknown) {
  187. //未知错误中尝试打印具体的错误信息
  188. if (e.error != null) {
  189. if (e.error.toString().contains("HandshakeException")) {
  190. return HttpResult(isSuccess: false, errorMsg: "网络连接错误,请检查网络连接");
  191. } else {
  192. return HttpResult(isSuccess: false, errorMsg: e.error.toString()); //这里打印的就是英文错误了,没有格式化
  193. }
  194. } else {
  195. return HttpResult(isSuccess: false, errorMsg: "网络请求出现未知错误");
  196. }
  197. } else {
  198. //如果有response走Api错误
  199. return HttpResult(isSuccess: false, errorMsg: e.message);
  200. }
  201. }
  202. }
  203. ///生成对应Get与Post的请求体,并封装对应的参数
  204. Future<Response> _generateRequest(
  205. HttpMethod? method,
  206. Map<String, dynamic>? params,
  207. Map<String, String>? paths, //文件
  208. Map<String, Uint8List>? pathStreams, //文件流
  209. String url,
  210. Map<String, String>? headers,
  211. CacheControl? cacheControl,
  212. Duration? cacheExpiration,
  213. ProgressCallback? send, // 上传进度监听
  214. ProgressCallback? receive, // 下载监听
  215. CancelToken? cancelToken, // 用于取消的 token,可以多个请求绑定一个 token
  216. ) async {
  217. if (method != null && method == HttpMethod.POST) {
  218. //以 Post 请求 FromData 的方式上传
  219. return networkEngine.executePost(
  220. url: url,
  221. params: params,
  222. paths: paths,
  223. pathStreams: pathStreams,
  224. headers: headers,
  225. send: send,
  226. receive: receive,
  227. cancelToken: cancelToken,
  228. );
  229. } else {
  230. //默认 Get 请求,添加逻辑是否需要处理缓存策略,具体缓存逻辑见拦截器
  231. if (cacheControl != null) {
  232. if (headers == null || headers.isEmpty) {
  233. headers = <String, String>{};
  234. }
  235. headers['cache_control'] = cacheControl.name;
  236. if (cacheExpiration != null) {
  237. headers['cache_expiration'] = cacheExpiration.inMilliseconds.toString();
  238. }
  239. }
  240. return networkEngine.executeGet(
  241. url: url,
  242. params: params,
  243. headers: headers,
  244. cacheControl: cacheControl,
  245. cacheExpiration: cacheExpiration,
  246. receive: receive,
  247. cancelToken: cancelToken,
  248. );
  249. }
  250. }
  251. @override
  252. String toString() {
  253. return "networkEngine 的 baseUrl:${networkEngine.baseUrl}";
  254. }
  255. }