Flutter之网络请求
Flutter之网络请求
一,介绍与需求
1.1,介绍
1,http一个可组合的,基于Future的库,用于发出HTTP请求。包含一组高级功能和类,可轻松使用HTTP资源。它与平台无关,可以在命令行和浏览器上使用。
2,Dart的功能强大的Http客户端,支持拦截器,全局配置,FormData,请求取消,文件下载,超时等。
1.2,需求
编写一个 App,最离不开的就是网络请求了。目前Flutter普及率也不是很高,网络请求大致分为如下三种方式:- Dart 原生的网络请求
HttpClient
- 库
http
- 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 Futureget(String url, {Map params}) async { 3 if (params != null && params.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 return res.body; 15 }
第四步:POST方式请求
1 // post请求 2 static Futurepost(String url, {Map params}) async { 3 http.Response res = await http.post(url, body: params, headers: getCommonHeader()); 4 print(res.statusCode); 5 return res.body; 6 }
其他请求方式与post方式类似,这儿就不一一列举其他请求方式了。
第五步:统一传参处理
1 static MapgetCommonHeader() { 2 Map header = Map(); 3 header['yingqi'] = "jackson影琪"; 4 return header; 5 }
第六步:完整代码
1 import 'dart:async'; 2 import 'package:http/http.dart' as http; 3 4 class NetUtils { 5 // get请求的封装,传入的两个参数分别是请求URL和请求参数,请求参数以map的形式传入,会在方法体中自动拼接到URL后面 6 static Futureget(String url, {Map params}) async { 7 if (params != null && params.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 return res.body; 19 } 20 21 // post请求 22 static Future post(String url, {Map params}) async { 23 http.Response res = await http.post(url, body: params, headers: getCommonHeader()); 24 print(res.statusCode); 25 return res.body; 26 } 27 28 // put请求 29 static Future put(String url, {Map params}) async { 30 http.Response res = await http.put(url, body: params, headers: getCommonHeader()); 31 return res.body; 32 } 33 34 static Map getCommonHeader() { 35 Map header = Map(); 36 header['yingqi'] = "1"; 37 return header; 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 = new BaseOptions( 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.interceptors 3 .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 return errorResponse; 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
第七步: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
第八步:POST方式请求-表单传值
1 //if (contentType == 'application/x-www-form-urlencoded') {//表单方式 2 var requestData = new FormData.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 void openDebug() { 14 _isDebug = true; 15 } 16 17 DioNetUtils._init() { 18 BaseOptions options = new BaseOptions( 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.interceptors 35 .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
** 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 Mapparams = 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 Future
2,页面调用
1 void getData() async { 2 Mapparams = 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,返回的结果