dio_utils.dart 8.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258
  1. import 'dart:convert';
  2. import 'dart:io';
  3. import 'package:dio/adapter.dart';
  4. import 'package:dio/dio.dart';
  5. import 'package:flustars/flustars.dart';
  6. import 'package:flutter/foundation.dart';
  7. import 'package:liftmanager/common/common.dart';
  8. import 'package:liftmanager/net/api_service.dart';
  9. import 'package:liftmanager/net/mock_data.dart';
  10. import 'package:liftmanager/utils/log_utils.dart';
  11. import 'package:rxdart/rxdart.dart';
  12. import 'base_entity.dart';
  13. import 'error_handle.dart';
  14. import 'intercept.dart';
  15. import 'package:liftmanager/utils/log_util.dart' as logg;
  16. import 'package:liftmanager/utils/url.dart';
  17. /// @weilu https://github.com/simplezhli
  18. class DioUtils {
  19. static final DioUtils _singleton = DioUtils._internal();
  20. static DioUtils get instance => DioUtils();
  21. factory DioUtils() {
  22. return _singleton;
  23. }
  24. static Dio _dio;
  25. Dio getDio() {
  26. return _dio;
  27. }
  28. DioUtils._internal() {
  29. var options = BaseOptions(
  30. connectTimeout: 150000,
  31. receiveTimeout: 15000,
  32. responseType: ResponseType.plain,
  33. validateStatus: (status) {
  34. // 不使用http状态码判断状态,使用AdapterInterceptor来处理(适用于标准REST风格)
  35. return true;
  36. },
  37. // baseUrl: "http://192.168.31.100:20250",
  38. // baseUrl: "http://192.168.1.4:20226",
  39. // baseUrl: "http://192.168.0.110:20250",
  40. // baseUrl: "http://192.168.31.112:20226",
  41. // baseUrl: "http://lift.whlhcx.com",
  42. // baseUrl: "http://111.47.6.224:10227",
  43. baseUrl: baseUrl,
  44. // baseUrl: "http://221.234.44.30:10227",
  45. // baseUrl: "http://192.168.1.16",
  46. // contentType: ContentType('application', 'x-www-form-urlencoded', charset: 'utf-8'),
  47. );
  48. _dio = Dio(options);
  49. /// Fiddler抓包代理配置 https://www.jianshu.com/p/d831b1f7c45b
  50. // (_dio.httpClientAdapter as DefaultHttpClientAdapter).onHttpClientCreate =
  51. // (HttpClient client) {
  52. // client.findProxy = (uri) {
  53. // //proxy all request to localhost:8888
  54. // return "PROXY 192.168.31.72:8686";
  55. // };
  56. // client.badCertificateCallback =
  57. // (X509Certificate cert, String host, int port) => true;
  58. // };
  59. /// 统一添加身份验证请求头
  60. _dio.interceptors.add(AuthInterceptor());
  61. /// 刷新Token
  62. // _dio.interceptors.add(TokenInterceptor());
  63. /// 打印Log(生产模式去除)
  64. if (!Constant.inProduction) {
  65. // _dio.interceptors.add(LoggingInterceptor());
  66. _dio.interceptors.add(
  67. InterceptorsWrapper(
  68. onRequest: (RequestOptions options) {
  69. print("\n================================= 请求数据 =================================");
  70. print("method = ${options.method.toString()}");
  71. print("url = ${options.uri.toString()}");
  72. print("headers = ${options.headers}");
  73. // print("params = ${options.queryParameters}");
  74. print("paramsData = ${options.data}");
  75. },
  76. onResponse: (Response response) {
  77. print("\n================================= 响应数据开始 =================================");
  78. print("StatusCode = ${response.statusCode}");
  79. logg.LogUtil.d("data = ${response.data}");
  80. },
  81. onError: (DioError e) {
  82. print("\n=================================错误响应数据 =================================");
  83. print("type = ${e.type}");
  84. print("message = ${e.message}");
  85. print("\n");
  86. },
  87. ),
  88. );
  89. }
  90. /// 适配数据(根据自己的数据结构,可自行选择添加)
  91. _dio.interceptors.add(AdapterInterceptor());
  92. }
  93. // 数据返回格式统一,统一处理异常
  94. Future<BaseEntity<T>> _request<T>(String method, String url,
  95. {T Function(Map<String, dynamic>) objectFromJson,
  96. dynamic data,
  97. Map<String, dynamic> queryParameters,
  98. CancelToken cancelToken,
  99. Options options}) async {
  100. var response = await _dio.request(url,
  101. data: data,
  102. queryParameters: queryParameters,
  103. options: _checkOptions(method, options),
  104. cancelToken: cancelToken);
  105. try {
  106. /// 集成测试无法使用 isolate
  107. Map<String, dynamic> _map = Constant.isTest
  108. ? parseData(response.data.toString())
  109. : await compute(parseData, response.data.toString());
  110. return BaseEntity.fromJson(_map, objectFromJson);
  111. } catch (e, s) {
  112. return BaseEntity(ExceptionHandle.parse_error, "数据解析错误${e}\n${s}", null);
  113. }
  114. }
  115. Options _checkOptions(method, options) {
  116. if (options == null) {
  117. options = new Options();
  118. }
  119. options.method = method;
  120. return options;
  121. }
  122. Future requestNetwork<T>(Method method, String url,
  123. {T Function(Map<String, dynamic>) objectFromJson,
  124. Function(T t) onSuccess,
  125. Function(List<T> list) onSuccessList,
  126. Function(int code, String msg) onError,
  127. dynamic params,
  128. Map<String, dynamic> queryParameters,
  129. CancelToken cancelToken,
  130. Options options,
  131. bool isList: false}) async {
  132. String m = _getRequestMethod(method);
  133. return await _request<T>(m, url,
  134. objectFromJson: objectFromJson,
  135. data: params,
  136. queryParameters: queryParameters,
  137. options: options,
  138. cancelToken: cancelToken)
  139. .then((BaseEntity<T> result) {
  140. // logg.LogUtil.d(params);
  141. if (result.statusCode == 1 || result.statusCode == 9) {
  142. if (isList) {
  143. if (onSuccessList != null) {
  144. onSuccessList(result.listData);
  145. }
  146. } else {
  147. if (onSuccess != null) {
  148. onSuccess(result.data);
  149. }
  150. }
  151. } else {
  152. _onError(result.statusCode, result.message, onError);
  153. }
  154. }, onError: (e, _) {
  155. _cancelLogPrint(e, url);
  156. NetError error = ExceptionHandle.handleException(e);
  157. _onError(error.code, error.msg, onError);
  158. });
  159. }
  160. /// 统一处理(onSuccess返回T对象,onSuccessList返回List<T>)
  161. asyncRequestNetwork<T>(Method method, String url,
  162. {Function(T t) onSuccess,
  163. Function(List<T> list) onSuccessList,
  164. Function(int code, String msg) onError,
  165. dynamic params,
  166. Map<String, dynamic> queryParameters,
  167. CancelToken cancelToken,
  168. Options options,
  169. bool isList: false}) {
  170. String m = _getRequestMethod(method);
  171. Observable.fromFuture(_request<T>(m, url,
  172. data: params,
  173. queryParameters: queryParameters,
  174. options: options,
  175. cancelToken: cancelToken))
  176. .asBroadcastStream()
  177. .listen((result) {
  178. if (result.statusCode == 1 || result.statusCode == 9) {
  179. if (isList) {
  180. if (onSuccessList != null) {
  181. onSuccessList(result.listData);
  182. }
  183. } else {
  184. if (onSuccess != null) {
  185. onSuccess(result.data);
  186. }
  187. }
  188. } else {
  189. _onError(result.statusCode, result.message, onError);
  190. }
  191. }, onError: (e) {
  192. _cancelLogPrint(e, url);
  193. NetError error = ExceptionHandle.handleException(e);
  194. _onError(error.code, error.msg, onError);
  195. });
  196. }
  197. _cancelLogPrint(dynamic e, String url) {
  198. if (e is DioError && CancelToken.isCancel(e)) {
  199. Log.e("取消请求接口: $url");
  200. }
  201. }
  202. _onError(int code, String msg, Function(int code, String mag) onError) {
  203. if (code == null) {
  204. code = ExceptionHandle.unknown_error;
  205. msg = "未知异常";
  206. }
  207. Log.e("接口请求异常: code: $code, mag: $msg");
  208. if (onError != null) {
  209. onError(code, msg);
  210. }
  211. }
  212. String _getRequestMethod(Method method) {
  213. String m;
  214. switch (method) {
  215. case Method.get:
  216. m = "GET";
  217. break;
  218. case Method.post:
  219. m = "POST";
  220. break;
  221. case Method.put:
  222. m = "PUT";
  223. break;
  224. case Method.patch:
  225. m = "PATCH";
  226. break;
  227. case Method.delete:
  228. m = "DELETE";
  229. break;
  230. case Method.head:
  231. m = "HEAD";
  232. break;
  233. }
  234. return m;
  235. }
  236. }
  237. Map<String, dynamic> parseData(String data) {
  238. return json.decode(data);
  239. }
  240. enum Method { get, post, put, patch, delete, head }