Flutter之网络请求
Flutter之网络请求
一,介绍与需求
1.1,介绍
1,http一个可组合的,基于Future的库,用于发出HTTP请求。包含一组高级功能和类,可轻松使用HTTP资源。它与平台无关,可以在命令行和浏览器上使用。
2,Dart的功能强大的Http客户端,支持拦截器,全局配置,FormData,请求取消,文件下载,超时等。
1.2,需求
- Dart 原生的网络请求
HttpClient - 库
http - Flutter中文网发布的
dio
本文主要介绍后面两种网络请求方式的封装与使用,dart的原生网络请求HttpClient可参考文档通过HttpClient发起HTTP请求
二,网络请求封装
第一步:添加依赖
打开 pubspec.yaml文件,在dependencies下添加如下包:
http: ^0.12.+
dio: ^3.0.
保存后,一般会自动下载包;如果没有自动下载可在项目根目录下运行如下命令,进行下载:
flutter packages get
2.1,http请求库
第二步:引入包并创建网络请求类
import 'package:http/http.dart' as http;
class NetUtils {
...
}
第三步:get方式请求
// get请求的封装,传入的两个参数分别是请求URL和请求参数,请求参数以map的形式传入,会在方法体中自动拼接到URL后面
static Future<String> get(String url, {Map<String, String> params}) async {
if (params != null && params.isNotEmpty) {
// 如果参数不为空,则将参数拼接到URL后面
StringBuffer sb = StringBuffer("?");
params.forEach((key, value) {
sb.write("$key" + "=" + "$value" + "&");
});
String paramStr = sb.toString();
paramStr = paramStr.substring(0, paramStr.length - 1);
url += paramStr;
}
http.Response res = await http.get(url, headers: getCommonHeader());
return res.body;
}
第四步:POST方式请求
// post请求
static Future<String> post(String url, {Map<String, String> params}) async {
http.Response res = await http.post(url, body: params, headers: getCommonHeader());
print(res.statusCode);
return res.body;
}
其他请求方式与post方式类似,这儿就不一一列举其他请求方式了。
第五步:统一传参处理
static Map<String, String> getCommonHeader() {
Map<String, String> header = Map();
header['yingqi'] = "jackson影琪";
return header;
}
第六步:完整代码
import 'dart:async';
import 'package:http/http.dart' as http; class NetUtils {
// get请求的封装,传入的两个参数分别是请求URL和请求参数,请求参数以map的形式传入,会在方法体中自动拼接到URL后面
static Future<String> get(String url, {Map<String, String> params}) async {
if (params != null && params.isNotEmpty) {
// 如果参数不为空,则将参数拼接到URL后面
StringBuffer sb = StringBuffer("?");
params.forEach((key, value) {
sb.write("$key" + "=" + "$value" + "&");
});
String paramStr = sb.toString();
paramStr = paramStr.substring(0, paramStr.length - 1);
url += paramStr;
}
http.Response res = await http.get(url, headers: getCommonHeader());
return res.body;
} // post请求
static Future<String> post(String url, {Map<String, String> params}) async {
http.Response res = await http.post(url, body: params, headers: getCommonHeader());
print(res.statusCode);
return res.body;
} // put请求
static Future<String> put(String url, {Map<String, String> params}) async {
http.Response res = await http.put(url, body: params, headers: getCommonHeader());
return res.body;
} static Map<String, String> getCommonHeader() {
Map<String, String> header = Map();
header['yingqi'] = "1";
return header;
} }
2.2,Dio
第二步:引入包并创建网络请求类
import 'dart:async';
import 'package:dio/dio.dart'; class DioNetUtils { ... }
第三步:初始化Dio
static final DioNetUtils _singleton = DioNetUtils._init();
static Dio _dio; DioNetUtils._init() {
BaseOptions options = new BaseOptions(
baseUrl: "http://192.168.1.19:8880",
connectTimeout: 1000 * 1,
receiveTimeout: 1000 * 2,
//Http请求头.
headers: {//可统一配置传参
//do something
"version": "1.0.0"
},
//请求的Content-Type,默认值是"application/json; charset=utf-8". 也可以用"application/x-www-form-urlencoded"
// contentType: "application/json; charset=utf-8",
//表示期望以那种格式(方式)接受响应数据。接受4种类型 `json`, `stream`, `plain`, `bytes`. 默认值是 `json`,
responseType: ResponseType.json,
);
_dio = Dio(options); }
第四步:添加拦截器
//添加拦截器
_dio.interceptors
.add(InterceptorsWrapper(onRequest: (RequestOptions options) {
print("请求之前处理");
return options; //continue
}, onResponse: (Response response) {
print("响应之前处理");
print(options);
return response; // continue
}, onError: (DioError e) {
print("错误之前提示");
Response errorInfo = _dealErrorInfo(e);
return errorInfo; //continue
}));
第五步:统一处理错误信息
_dealErrorInfo(error) {
print(error.type);
// 请求错误处理
Response errorResponse;
if (error.response != null) {
errorResponse = error.response;
} else {
errorResponse = new Response(statusCode: 201);
}
// 请求超时
if (error.type == DioErrorType.CONNECT_TIMEOUT) {
ShowToast.warning("网络请求超时,请稍后重试");
errorResponse.statusCode = ResultCode.CONNECT_TIMEOUT;
}
// 请求连接超时
else if (error.type == DioErrorType.RECEIVE_TIMEOUT) {
ShowToast.warning("网络连接超时,请稍后重试");
errorResponse.statusCode = ResultCode.RECEIVE_TIMEOUT;
}
// 服务器错误
else if (error.type == DioErrorType.RESPONSE) {
ShowToast.warning("服务器繁忙,请稍后重试");
errorResponse.statusCode = ResultCode.RESPONSE;
}
// 一般服务器错误
else {
ShowToast.warning("网络连接不可用,请稍后重试1");
errorResponse.statusCode = ResultCode.DEFAULT;
}
return errorResponse;
}
第六步:GET方式请求
/// Make http request with options.
/// [method] The request method.
/// [path] The url path.
/// [data] The request data
/// [options] The request options.
/// String 返回 json data .
Future<Map> request<T>(
String path, {
String method = Method.get,
String contentType= "application/json; charset=utf-8",
queryParameters,
Options options,
// CancelToken cancelToken,
}) async {
print('path===' + path);
Response response = await _dio.request(
path,
queryParameters: queryParameters,
options: _checkOptions(method, contentType, options),
// cancelToken: cancelToken,
);
_printHttpLog(response);
if (response.statusCode == 200) {
try {
if (response.data is Map) {
if (response.data["httpCode"] != 200) {
ShowToast.warning(response.data["message"]);
return new Future.error(new DioError(
response: response,
type: DioErrorType.RESPONSE,
));
}
// 由于不同的接口返回的格式不固定不规范,所以需要根据接口格式自定义.
return response.data['data'];
} else {
if (response.data is List) {
Map<String, dynamic> _dataMap = Map();
_dataMap["data"] = response.data;
return _dataMap;
}
}
} catch (e) {
ShowToast.warning("网络连接不可用,请稍后重试");
return new Future.error(new DioError(
response: response,
// message: "data parsing exception...",
type: DioErrorType.RESPONSE,
));
}
}
ShowToast.warning("网络连接不可用,请稍后重试");
return new Future.error(new DioError(
response: response,
type: DioErrorType.RESPONSE,
));
}
第七步:POST方式请求-json传值
/// Make http request with options.
/// [method] The request method.
/// [path] The url path.
/// [data] The request data
/// [options] The request options.
/// String 返回 json data .
Future<Map> request<T>(
String path, {
String method = Method.get,
String contentType= "application/json; charset=utf-8",
queryParameters,
Options options,
// CancelToken cancelToken,
}) async {
print('path===' + path);
Response response;
if (method == Method.get) {
//GET方式 ... } else {
//除GET的其他方式
var requestData = queryParameters;
response = await _dio.request(
path,
data: requestData,
options: _checkOptions(method, contentType, options),
// cancelToken: cancelToken,
);
} _printHttpLog(response);
if (response.statusCode == 200) { ... } ... }
第八步:POST方式请求-表单传值
//if (contentType == 'application/x-www-form-urlencoded') {//表单方式
var requestData = new FormData.fromMap({
"name": "jackson影琪",
"age": 25,
});
第九步:请求日志处理
// print Http Log.
void _printHttpLog(Response response) {
print(!_isDebug);
if (!_isDebug) {
return;
}
try {
print("----------------Http Log Start----------------" +
_getOptionsStr(response.request));
print(response);
print("----------------Http Log end----------------");
} catch (ex) {
print("Http Log" + " error......");
}
} // get Options Str.
String _getOptionsStr(RequestOptions request) {
return "method: " +
request.method +
" baseUrl: " +
request.baseUrl +
" path: " +
request.path;
}
第10步:完整代码
import 'dart:async';
import 'package:dio/dio.dart';
import 'ShowToastUtils.dart'; class DioNetUtils {
static final DioNetUtils _singleton = DioNetUtils._init();
static Dio _dio; /// 是否是debug模式.
static bool _isDebug = true; /// 打开debug模式.
static void openDebug() {
_isDebug = true;
} DioNetUtils._init() {
BaseOptions options = new BaseOptions(
baseUrl: "http://192.168.1.19:8880",
connectTimeout: 1000 * 1,
receiveTimeout: 1000 * 2,
//Http请求头.
headers: {
//do something
"version": "1.0.0"
},
//请求的Content-Type,默认值是"application/json; charset=utf-8". 也可以用"application/x-www-form-urlencoded"
// contentType: "application/json; charset=utf-8",
//表示期望以那种格式(方式)接受响应数据。接受4种类型 `json`, `stream`, `plain`, `bytes`. 默认值是 `json`,
responseType: ResponseType.json,
);
_dio = Dio(options);
//添加拦截器
_dio.interceptors
.add(InterceptorsWrapper(onRequest: (RequestOptions options) {
print("请求之前处理");
return options; //continue
}, onResponse: (Response response) {
print("响应之前处理");
print(options);
return response; // continue
}, onError: (DioError e) {
print("错误之前提示");
Response errorInfo = _dealErrorInfo(e);
return errorInfo; //continue
}));
} factory DioNetUtils() {
return _singleton;
} /// Make http request with options.
/// [method] The request method.
/// [path] The url path.
/// [data] The request data
/// [options] The request options.
/// String 返回 json data .
Future<Map> request<T>(
String path, {
String method = Method.get,
String contentType= "application/json; charset=utf-8",
queryParameters,
Options options,
// CancelToken cancelToken,
}) async {
print('path===' + path);
Response response;
if (method == Method.get) {
//GET方式
response = await _dio.request(
path,
queryParameters: queryParameters,
options: _checkOptions(method, contentType, options),
// cancelToken: cancelToken,
);
} else {
//除GET的其他方式
var requestData;
print(contentType);
if (contentType == 'application/x-www-form-urlencoded') {//表单方式
requestData = new FormData.fromMap({
"name": "jackson影琪",
"age": 25,
});
}else{//json格式
requestData = queryParameters;
}
response = await _dio.request(
path,
data: requestData,
options: _checkOptions(method, contentType, options),
// cancelToken: cancelToken,
);
} _printHttpLog(response);
if (response.statusCode == 200) {
try {
if (response.data is Map) {
if (response.data["httpCode"] != 200) {
ShowToast.warning(response.data["message"]);
return new Future.error(new DioError(
response: response,
type: DioErrorType.RESPONSE,
));
}
// 由于不同的接口返回的格式不固定不规范,所以需要根据接口格式自定义.
return response.data['data'];
} else {
if (response.data is List) {
Map<String, dynamic> _dataMap = Map();
_dataMap["data"] = response.data;
return _dataMap;
}
}
} catch (e) {
ShowToast.warning("网络连接不可用,请稍后重试");
return new Future.error(new DioError(
response: response,
// message: "data parsing exception...",
type: DioErrorType.RESPONSE,
));
}
}
ShowToast.warning("网络连接不可用,请稍后重试");
return new Future.error(new DioError(
response: response,
type: DioErrorType.RESPONSE,
));
} /// check Options.
Options _checkOptions(method, contentType, options) {
if (options == null) {
options = new Options();
}
// if (contentType) {
// //设置请求的类型 json 表单
// options.contentType = contentType;
// }
options.method = method;
return options;
} // print Http Log.
void _printHttpLog(Response response) {
print(!_isDebug);
if (!_isDebug) {
return;
}
try {
print("----------------Http Log Start----------------" +
_getOptionsStr(response.request));
print(response);
print("----------------Http Log end----------------");
} catch (ex) {
print("Http Log" + " error......");
}
} // get Options Str.
String _getOptionsStr(RequestOptions request) {
return "method: " +
request.method +
" baseUrl: " +
request.baseUrl +
" path: " +
request.path;
} // 错误全局处理
_dealErrorInfo(error) {
print(error.type);
// 请求错误处理
Response errorResponse;
if (error.response != null) {
errorResponse = error.response;
} else {
errorResponse = new Response(statusCode: 201);
}
// 请求超时
if (error.type == DioErrorType.CONNECT_TIMEOUT) {
ShowToast.warning("网络请求超时,请稍后重试");
errorResponse.statusCode = ResultCode.CONNECT_TIMEOUT;
}
// 请求连接超时
else if (error.type == DioErrorType.RECEIVE_TIMEOUT) {
ShowToast.warning("网络连接超时,请稍后重试");
errorResponse.statusCode = ResultCode.RECEIVE_TIMEOUT;
}
// 服务器错误
else if (error.type == DioErrorType.RESPONSE) {
ShowToast.warning("服务器繁忙,请稍后重试");
errorResponse.statusCode = ResultCode.RESPONSE;
}
// 一般服务器错误
else {
ShowToast.warning("网络连接不可用,请稍后重试1");
errorResponse.statusCode = ResultCode.DEFAULT;
}
return errorResponse;
}
} abstract class DioCallback<T> {
void onSuccess(T t); void onError(DioError error);
}
** dio网络请求失败的回调错误码 **
/*
* dio网络请求失败的回调错误码 自定义
*/
class ResultCode {
//正常返回是1
static const SUCCESS = 1; //异常返回是0
static const ERROR = 0; /// When opening url timeout, it occurs.
static const CONNECT_TIMEOUT = -1; ///It occurs when receiving timeout.
static const RECEIVE_TIMEOUT = -2; /// When the server response, but with a incorrect status, such as 404, 503...
static const RESPONSE = -3; /// When the request is cancelled, dio will throw a error with this type.
static const CANCEL = -4; /// read the DioError.error if it is not null.
static const DEFAULT = -5;
}
** dio网络请求方式 **
/// 请求方法.
class Method {
static const String get = "GET";
static final String post = "POST";
static final String put = "PUT";
static final String head = "HEAD";
static final String delete = "DELETE";
static final String patch = "PATCH";
}
三,接口调用
3.1,http请求库
1,页面调用
Map<String, String> params = Map();
params['loginCode'] = _unameController.text;
params['password'] = _pwdController.text;
NetUtils.post(ServiceApi.loginAction, params: params).then((data) {
print(ServiceApi.loginAction);
print(data);
}).catchError((e) {
Toast.toast(
context,
msg: '网络请求出错:$e,请稍后重试!',
position: 'top',
bgColor: Color.fromRGBO(130, 0, 0, 1), // Color 提示框背景颜色
textColor: Color.fromRGBO(250, 100, 100, 1), // Color 提示框文字颜色
);
});
3.2,Dio
1,服务接口地址
import 'dart:async';
import '../util/DioNetUtils.dart';
class ServiceNetApi {
///获取用户信息
Future<Map> getSingleDataById(data) async {
return await DioNetUtils().request<String>(
"/**/**/yingqi/**/getSingleDataById",
queryParameters: data,
method:Method.put
);
}
}
2,页面调用
void getData() async {
Map<String, String> params = Map();
params['Id'] = "123456789";
params['Name'] = "jackson影琪";
await ServiceNetApi().getSingleDataById(params).then((json) {
print('getSingleDataById');
print(json);
}).catchError((e) {
});
}
3,返回的结果

下一章->待定
Flutter之网络请求的更多相关文章
- flutter dio网络请求封装实现
flutter dio网络请求封装实现 文章友情链接: https://juejin.im/post/6844904098643312648 在Flutter项目中使用网络请求的方式大致可分为两种 ...
- 【技术博客】Flutter—使用网络请求的页面搭建流程、State生命周期、一些组件的应用
Flutter-使用网络请求的页面搭建流程.State生命周期.一些组件的应用 使用网络请求的页面搭建流程 在开发APP时,我们常常会遇到如下场景:进入一个页面后,要先进行网络调用,然后使用调用返 ...
- Flutter -------- dio网络请求
dio是Flutter中文网开源的一个强大的Dart Http请求库,支持Restful API.FormData.拦截器.请求取消.Cookie管理.文件上传/下载.超时等... 1.添加依赖# d ...
- Flutter网络请求和数据解析
一:前言 - 什么是反射机制,Flutter为什么禁用反射机制? 在Flutter中它的网络请求和数据解析稍微的比较麻烦一点,因为Flutter不支持反射机制.相信大家都看到这么一条,就是Flutte ...
- 从零学习Fluter(五):Flutter中手势滑动拖动已经网络请求
从六号开始搞Flutter,到今天写这篇blog已经过了4天时间,文档初步浏览了一遍,写下了这个demo.demo源码分享在github上,现在对flutter有种说不出的喜欢了.大家一起搞吧! 废话 ...
- Flutter 网络请求库http
http 集成http库 https://pub.dartlang.org/packages/http 添加依赖 dependencies: http: ^ 安装 flutter packages g ...
- Flutter网络请求与JSON解析
本文介绍如何在Flutter中创建HTTP网络请求和对请求的json string进行类型解析. 网络请求 官方使用的是用dart io中的HttpClient发起的请求,但HttpClient本身功 ...
- Flutter -------- Http库 网络请求封装(HttpController)
http库 再次封装的网络请求类 HttpController 1.添加依赖 dependencies: http: ^0.12.0 #latest version 2.导入库 import 'pac ...
- Flutter -------- 网络请求之HttpClient
今天来说说Flutter中的网络请求,HttpClient网络请求,包含get,post get var data; _get() async { Map newTitle; var response ...
随机推荐
- 前端开发常用 JS 方法
1,获取文件本地url,在上传之前预览 /** * 获取图片嗯滴url,在上传之前预览 * @param file 选择的图片文件 * @returns {*} url */ getFileLocat ...
- [转]Python实现字符串反转的几种方法
#第一种:使用字符串切片 result = s[::-1] #第二种:使用列表的reverse方法 l = list(s) l.reverse() result = "".join ...
- Python基础之shutil模块、random模块
1.shutil模块 shutil模块是对os模块的功能补充,包含移动.复制.打包.压缩.解压等功能. 1)shutil.copyfileobj() 复制文件内容到另一个文件,可指定大小内容,如len ...
- Windows中常用工具
护眼软件 f.lux https://justgetflux.com/ Typora https://www.typora.io/ Markdown工具,小巧,方便. Snipaste https:/ ...
- 全面了解Cookie
一.Cookie的出现 浏览器和服务器之间的通信少不了HTTP协议,但是因为HTTP协议是无状态的,所以服务器并不知道上一次浏览器做了什么样的操作,这样严重阻碍了交互式Web应用程序的实现. 针对上述 ...
- Python列表,元组,字典,集合
列表 Python中列表是可变的,这是它区别于字符串和元组的最重要的特点,一句话概括即:列表可以修改,而字符串和元组不能. 列表追加数据的方法:append(),extend(数组),insert(位 ...
- Nginx配置多域名代理
目的 当我们有多个站点需要对外网开放,每个站点的域名都不一样,然而我们只有一个外网ip.这种情况下,我们就可以使用一个Nginx来配置多域名代理.这种代理方式可以解决,在同一个端口上针对不同域名代理不 ...
- 搜索和浏览离线 Wikipedia 维基百科(中/英)数据工具
为什么使用离线维基百科?一是因为最近英文维基百科被封,无法访问:二是不受网络限制,使用方便,缺点是不能及时更新,可能会有不影响阅读的乱码. 目前,主要有两种工具用来搜索和浏览离线维基百科数据:Kiwi ...
- Redis SCAN命令实现有限保证的原理
SCAN命令可以为用户保证:从完整遍历开始直到完整遍历结束期间,一直存在于数据集内的所有元素都会被完整遍历返回,但是同一个元素可能会被返回多次.如果一个元素是在迭代过程中被添加到数据集的,又或者是在迭 ...
- Django 之 ContentType组件
一.什么是 ContentTypes ContentTypes 是 Django 内置的一个应用,它可以追踪记录项目中所有 app 和 model 的对应关系,并记录在 django_content_ ...