赞
踩
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,返回的结果
下一章->待定
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。