当前位置:   article > 正文

flutter 怎么拦截请求_Flutter之网络请求

flutter 请求拦截

Flutter之网络请求

一,介绍与需求

1.1,介绍

1,http一个可组合的,基于Future的库,用于发出HTTP请求。包含一组高级功能和类,可轻松使用HTTP资源。它与平台无关,可以在命令行和浏览器上使用。

2,Dart的功能强大的Http客户端,支持拦截器,全局配置,FormData,请求取消,文件下载,超时等。

1.2,需求

编写一个 App,最离不开的就是网络请求了。目前Flutter普及率也不是很高,网络请求大致分为如下三种方式:

Dart 原生的网络请求HttpClient

Flutter中文网发布的 dio

本文主要介绍后面两种网络请求方式的封装与使用,dart的原生网络请求HttpClient可参考文档通过HttpClient发起HTTP请求

二,网络请求封装

第一步:添加依赖

打开 pubspec.yaml文件,在dependencies下添加如下包:

1 http: ^0.12.0+2

2 dio: ^3.0.4

保存后,一般会自动下载包;如果没有自动下载可在项目根目录下运行如下命令,进行下载:

1 flutter packages get

2.1,http请求库

第二步:引入包并创建网络请求类

1 import 'package:http/http.dart' as http;

1 class NetUtils {2

3 ...4

5 }

第三步:get方式请求

1 //get请求的封装,传入的两个参数分别是请求URL和请求参数,请求参数以map的形式传入,会在方法体中自动拼接到URL后面

2 static Future get(String url, {Mapparams}) async {3 if (params != null &¶ms.isNotEmpty) {4 //如果参数不为空,则将参数拼接到URL后面

5 StringBuffer sb = StringBuffer("?");6 params.forEach((key, value) {7 sb.write("$key" + "=" + "$value" + "&");8 });9 String paramStr =sb.toString();10 paramStr = paramStr.substring(0, paramStr.length - 1);11 url +=paramStr;12 }13 http.Response res =await http.get(url, headers: getCommonHeader());14 returnres.body;15 }

第四步:POST方式请求

1 //post请求

2 static Future post(String url, {Mapparams}) async {3 http.Response res =await http.post(url, body: params, headers: getCommonHeader());4 print(res.statusCode);5 returnres.body;6 }

其他请求方式与post方式类似,这儿就不一一列举其他请求方式了。

第五步:统一传参处理

1 static MapgetCommonHeader() {2 Map header =Map();3 header['yingqi'] = "jackson影琪";4 returnheader;5 }

第六步:完整代码

1 import 'dart:async';2 import 'package:http/http.dart'as http;3

4 class NetUtils {5 //get请求的封装,传入的两个参数分别是请求URL和请求参数,请求参数以map的形式传入,会在方法体中自动拼接到URL后面

6 static Future get(String url, {Mapparams}) async {7 if (params != null &¶ms.isNotEmpty) {8 //如果参数不为空,则将参数拼接到URL后面

9 StringBuffer sb = StringBuffer("?");10 params.forEach((key, value) {11 sb.write("$key" + "=" + "$value" + "&");12 });13 String paramStr =sb.toString();14 paramStr = paramStr.substring(0, paramStr.length - 1);15 url +=paramStr;16 }17 http.Response res =await http.get(url, headers: getCommonHeader());18 returnres.body;19 }20

21 //post请求

22 static Future post(String url, {Mapparams}) async {23 http.Response res =await http.post(url, body: params, headers: getCommonHeader());24 print(res.statusCode);25 returnres.body;26 }27

28 //put请求

29 static Future put(String url, {Mapparams}) async {30 http.Response res =await http.put(url, body: params, headers: getCommonHeader());31 returnres.body;32 }33

34 static MapgetCommonHeader() {35 Map header =Map();36 header['yingqi'] = "1";37 returnheader;38 }39

40 }

2.2,Dio

第二步:引入包并创建网络请求类

1 import 'dart:async';2 import 'package:dio/dio.dart';3

4 class DioNetUtils {5

6 ...7

8 }

第三步:初始化Dio

1 static final DioNetUtils _singleton =DioNetUtils._init();2 static Dio _dio;3

4 DioNetUtils._init() {5 BaseOptions options = newBaseOptions(6 baseUrl: "http://192.168.1.19:8880",7 connectTimeout: 1000 * 1,8 receiveTimeout: 1000 * 2,9 //Http请求头.

10 headers: {//可统一配置传参

11 //do something

12 "version": "1.0.0"

13 },14 //请求的Content-Type,默认值是"application/json; charset=utf-8". 也可以用"application/x-www-form-urlencoded"

15 //contentType: "application/json; charset=utf-8",

16 //表示期望以那种格式(方式)接受响应数据。接受4种类型 `json`, `stream`, `plain`, `bytes`. 默认值是 `json`,

17 responseType: ResponseType.json,18 );19 _dio =Dio(options);20

21 }

第四步:添加拦截器

1 //添加拦截器

2 _dio.interceptors3 .add(InterceptorsWrapper(onRequest: (RequestOptions options) {4 print("请求之前处理");5 return options; //continue

6 }, onResponse: (Response response) {7 print("响应之前处理");8 print(options);9 return response; //continue

10 }, onError: (DioError e) {11 print("错误之前提示");12 Response errorInfo =_dealErrorInfo(e);13 return errorInfo; //continue

14 }));

第五步:统一处理错误信息

1 _dealErrorInfo(error) {2 print(error.type);3 //请求错误处理

4 Response errorResponse;5 if (error.response != null) {6 errorResponse =error.response;7 } else{8 errorResponse = new Response(statusCode: 201);9 }10 //请求超时

11 if (error.type ==DioErrorType.CONNECT_TIMEOUT) {12 ShowToast.warning("网络请求超时,请稍后重试");13 errorResponse.statusCode =ResultCode.CONNECT_TIMEOUT;14 }15 //请求连接超时

16 else if (error.type ==DioErrorType.RECEIVE_TIMEOUT) {17 ShowToast.warning("网络连接超时,请稍后重试");18 errorResponse.statusCode =ResultCode.RECEIVE_TIMEOUT;19 }20 //服务器错误

21 else if (error.type ==DioErrorType.RESPONSE) {22 ShowToast.warning("服务器繁忙,请稍后重试");23 errorResponse.statusCode =ResultCode.RESPONSE;24 }25 //一般服务器错误

26 else{27 ShowToast.warning("网络连接不可用,请稍后重试1");28 errorResponse.statusCode =ResultCode.DEFAULT;29 }30 returnerrorResponse;31 }

第六步:GET方式请求

1 /// Make http request with options.

2 /// [method] The request method.

3 /// [path] The url path.

4 /// [data] The request data

5 /// [options] The request options.

6 /// String 返回 json data .

7 Future request(8 String path, {9 String method =Method.get,10 String contentType= "application/json; charset=utf-8",11 queryParameters,12 Options options,13 //CancelToken cancelToken,

14 }) async {15 print('path===' +path);16 Response response =await _dio.request(17 path,18 queryParameters: queryParameters,19 options: _checkOptions(method, contentType, options),20 //cancelToken: cancelToken,

21 );22 _printHttpLog(response);23 if (response.statusCode == 200) {24 try{25 if(response.data is Map) {26 if (response.data["httpCode"] != 200) {27 ShowToast.warning(response.data["message"]);28 return new Future.error(newDioError(29 response: response,30 type: DioErrorType.RESPONSE,31 ));32 }33 //由于不同的接口返回的格式不固定不规范,所以需要根据接口格式自定义.

34 return response.data['data'];35 } else{36 if(response.data is List) {37 Map _dataMap =Map();38 _dataMap["data"] =response.data;39 return_dataMap;40 }41 }42 } catch(e) {43 ShowToast.warning("网络连接不可用,请稍后重试");44 return new Future.error(newDioError(45 response: response,46 //message: "data parsing exception...",

47 type: DioErrorType.RESPONSE,48 ));49 }50 }51 ShowToast.warning("网络连接不可用,请稍后重试");52 return new Future.error(newDioError(53 response: response,54 type: DioErrorType.RESPONSE,55 ));56 }

第七步:POST方式请求-json传值

1 /// Make http request with options.

2 /// [method] The request method.

3 /// [path] The url path.

4 /// [data] The request data

5 /// [options] The request options.

6 /// String 返回 json data .

7 Future request(8 String path, {9 String method =Method.get,10 String contentType= "application/json; charset=utf-8",11 queryParameters,12 Options options,13 //CancelToken cancelToken,

14 }) async {15 print('path===' +path);16 Response response;17 if (method ==Method.get) {18 //GET方式

19

20 ...21

22 } else{23 //除GET的其他方式

24 var requestData =queryParameters;25 response =await _dio.request(26 path,27 data: requestData,28 options: _checkOptions(method, contentType, options),29 //cancelToken: cancelToken,

30 );31 }32

33 _printHttpLog(response);34 if (response.statusCode == 200) {35

36 ...37

38 }39

40 ...41

42 }

第八步:POST方式请求-表单传值

1 //if (contentType == 'application/x-www-form-urlencoded') {//表单方式

2 var requestData = newFormData.fromMap({3 "name": "jackson影琪",4 "age": 25,5 });

第九步:请求日志处理

1 //print Http Log.

2 void_printHttpLog(Response response) {3 print(!_isDebug);4 if (!_isDebug) {5 return;6 }7 try{8 print("----------------Http Log Start----------------" +

9 _getOptionsStr(response.request));10 print(response);11 print("----------------Http Log end----------------");12 } catch(ex) {13 print("Http Log" + " error......");14 }15 }16

17 //get Options Str.

18 String _getOptionsStr(RequestOptions request) {19 return "method: " +

20 request.method +

21 " baseUrl: " +

22 request.baseUrl +

23 " path: " +

24 request.path;25 }

第10步:完整代码

1 import 'dart:async';2 import 'package:dio/dio.dart';3 import 'ShowToastUtils.dart';4

5 class DioNetUtils {6 static final DioNetUtils _singleton =DioNetUtils._init();7 static Dio _dio;8

9 /// 是否是debug模式.

10 static bool _isDebug = true;11

12 /// 打开debug模式.

13 static voidopenDebug() {14 _isDebug = true;15 }16

17 DioNetUtils._init() {18 BaseOptions options = newBaseOptions(19 baseUrl: "http://192.168.1.19:8880",20 connectTimeout: 1000 * 1,21 receiveTimeout: 1000 * 2,22 //Http请求头.

23 headers: {24 //do something

25 "version": "1.0.0"

26 },27 //请求的Content-Type,默认值是"application/json; charset=utf-8". 也可以用"application/x-www-form-urlencoded"

28 //contentType: "application/json; charset=utf-8",

29 //表示期望以那种格式(方式)接受响应数据。接受4种类型 `json`, `stream`, `plain`, `bytes`. 默认值是 `json`,

30 responseType: ResponseType.json,31 );32 _dio =Dio(options);33 //添加拦截器

34 _dio.interceptors35 .add(InterceptorsWrapper(onRequest: (RequestOptions options) {36 print("请求之前处理");37 return options; //continue

38 }, onResponse: (Response response) {39 print("响应之前处理");40 print(options);41 return response; //continue

42 }, onError: (DioError e) {43 print("错误之前提示");44 Response errorInfo =_dealErrorInfo(e);45 return errorInfo; //continue

46 }));47 }48

49 factory DioNetUtils() {50 return_singleton;51 }52

53 /// Make http request with options.

54 /// [method] The request method.

55 /// [path] The url path.

56 /// [data] The request data

57 /// [options] The request options.

58 /// String 返回 json data .

59 Future request(60 String path, {61 String method =Method.get,62 String contentType= "application/json; charset=utf-8",63 queryParameters,64 Options options,65 //CancelToken cancelToken,

66 }) async {67 print('path===' +path);68 Response response;69 if (method ==Method.get) {70 //GET方式

71 response =await _dio.request(72 path,73 queryParameters: queryParameters,74 options: _checkOptions(method, contentType, options),75 //cancelToken: cancelToken,

76 );77 } else{78 //除GET的其他方式

79 varrequestData;80 print(contentType);81 if (contentType == 'application/x-www-form-urlencoded') {//表单方式

82 requestData = newFormData.fromMap({83 "name": "jackson影琪",84 "age": 25,85 });86 }else{//json格式

87 requestData =queryParameters;88 }89 response =await _dio.request(90 path,91 data: requestData,92 options: _checkOptions(method, contentType, options),93 //cancelToken: cancelToken,

94 );95 }96

97 _printHttpLog(response);98 if (response.statusCode == 200) {99 try{100 if(response.data is Map) {101 if (response.data["httpCode"] != 200) {102 ShowToast.warning(response.data["message"]);103 return new Future.error(newDioError(104 response: response,105 type: DioErrorType.RESPONSE,106 ));107 }108 //由于不同的接口返回的格式不固定不规范,所以需要根据接口格式自定义.

109 return response.data['data'];110 } else{111 if(response.data is List) {112 Map _dataMap =Map();113 _dataMap["data"] =response.data;114 return_dataMap;115 }116 }117 } catch(e) {118 ShowToast.warning("网络连接不可用,请稍后重试");119 return new Future.error(newDioError(120 response: response,121 //message: "data parsing exception...",

122 type: DioErrorType.RESPONSE,123 ));124 }125 }126 ShowToast.warning("网络连接不可用,请稍后重试");127 return new Future.error(newDioError(128 response: response,129 type: DioErrorType.RESPONSE,130 ));131 }132

133 /// check Options.

134 Options _checkOptions(method, contentType, options) {135 if (options == null) {136 options = newOptions();137 }138 //if (contentType) {

139 设置请求的类型 json 表单

140 //options.contentType = contentType;

141 //}

142 options.method =method;143 returnoptions;144 }145

146 //print Http Log.

147 void_printHttpLog(Response response) {148 print(!_isDebug);149 if (!_isDebug) {150 return;151 }152 try{153 print("----------------Http Log Start----------------" +

154 _getOptionsStr(response.request));155 print(response);156 print("----------------Http Log end----------------");157 } catch(ex) {158 print("Http Log" + " error......");159 }160 }161

162 //get Options Str.

163 String _getOptionsStr(RequestOptions request) {164 return "method: " +

165 request.method +

166 " baseUrl: " +

167 request.baseUrl +

168 " path: " +

169 request.path;170 }171

172 //错误全局处理

173 _dealErrorInfo(error) {174 print(error.type);175 //请求错误处理

176 Response errorResponse;177 if (error.response != null) {178 errorResponse =error.response;179 } else{180 errorResponse = new Response(statusCode: 201);181 }182 //请求超时

183 if (error.type ==DioErrorType.CONNECT_TIMEOUT) {184 ShowToast.warning("网络请求超时,请稍后重试");185 errorResponse.statusCode =ResultCode.CONNECT_TIMEOUT;186 }187 //请求连接超时

188 else if (error.type ==DioErrorType.RECEIVE_TIMEOUT) {189 ShowToast.warning("网络连接超时,请稍后重试");190 errorResponse.statusCode =ResultCode.RECEIVE_TIMEOUT;191 }192 //服务器错误

193 else if (error.type ==DioErrorType.RESPONSE) {194 ShowToast.warning("服务器繁忙,请稍后重试");195 errorResponse.statusCode =ResultCode.RESPONSE;196 }197 //一般服务器错误

198 else{199 ShowToast.warning("网络连接不可用,请稍后重试1");200 errorResponse.statusCode =ResultCode.DEFAULT;201 }202 returnerrorResponse;203 }204 }205

206 abstract class DioCallback{207 voidonSuccess(T t);208

209 voidonError(DioError error);210 }

** dio网络请求失败的回调错误码 **

1 /*

2 * dio网络请求失败的回调错误码 自定义3 */

4 class ResultCode {5 //正常返回是1

6 static const SUCCESS = 1;7

8 //异常返回是0

9 static const ERROR = 0;10

11 /// When opening url timeout, it occurs.

12 static const CONNECT_TIMEOUT = -1;13

14 ///It occurs when receiving timeout.

15 static const RECEIVE_TIMEOUT = -2;16

17 /// When the server response, but with a incorrect status, such as 404, 503...

18 static const RESPONSE = -3;19

20 /// When the request is cancelled, dio will throw a error with this type.

21 static const CANCEL = -4;22

23 /// read the DioError.error if it is not null.

24 static const DEFAULT = -5;25 }

** dio网络请求方式 **

1 /// 请求方法.

2 class Method {3 static const String get = "GET";4 static final String post = "POST";5 static final String put = "PUT";6 static final String head = "HEAD";7 static final String delete = "DELETE";8 static final String patch = "PATCH";9 }

三,接口调用

3.1,http请求库

1,页面调用

1 Map params =Map();2 params['loginCode'] =_unameController.text;3 params['password'] =_pwdController.text;4 NetUtils.post(ServiceApi.loginAction, params: params).then((data) {5 print(ServiceApi.loginAction);6 print(data);7 }).catchError((e) {8 Toast.toast(9 context,10 msg: '网络请求出错:$e,请稍后重试!',11 position: 'top',12 bgColor: Color.fromRGBO(130, 0, 0, 1), //Color 提示框背景颜色

13 textColor: Color.fromRGBO(250, 100, 100, 1), //Color 提示框文字颜色

14 );15 });

3.2,Dio

1,服务接口地址

1 import 'dart:async';2

3 import '../util/DioNetUtils.dart';4

5 class ServiceNetApi {6 ///获取用户信息

7 FuturegetSingleDataById(data) async {8 return await DioNetUtils().request(9 "/**/**/yingqi/**/getSingleDataById",10 queryParameters: data,11 method:Method.put12 );13 }14 }

2,页面调用

1 voidgetData() async {2 Map params =Map();3 params['Id'] = "123456789";4 params['Name'] = "jackson影琪";5 await ServiceNetApi().getSingleDataById(params).then((json) {6 print('getSingleDataById');7 print(json);8 }).catchError((e) {9

10 });11 }

3,返回的结果

下一章->待定

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/Gausst松鼠会/article/detail/521622
推荐阅读
相关标签
  

闽ICP备14008679号