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
JS 代码如下 PS:我找的原代码中, 注释部分是没有注释的,但是调试的时候报错,就注释掉了,因为我只需要微信和支付宝的判定,所以这个地方,就没仔细研究 var isLppzApp = false ...
- 2019 翔通动漫java面试笔试题 (含面试题解析)
本人5年开发经验.18年年底开始跑路找工作,在互联网寒冬下成功拿到阿里巴巴.今日头条.翔通动漫等公司offer,岗位是Java后端开发,因为发展原因最终选择去了翔通动漫,入职一年时间了,也成为了面 ...
- 【Java】调用摄像头进行拍照并保存【详细】以及处理no jniopencv_core in java.library.path的一种方法
[之前困扰笔者的问题描述] date:2019.12.18 网上教程很多,但是没有看见完整的,所以写一个出来. 调用摄像头需要javaCV的jar包和openCV的jar包,现在已经不需要安装包了 ...
- Java自学-数字与字符串 格式化输出
Java 使用printf或format 进行格式化输出 步骤 1 : 格式化输出 如果不使用格式化输出,就需要进行字符串连接,如果变量比较多,拼接就会显得繁琐 使用格式化输出,就可以简洁明了 %s ...
- MFC 解决绘图时闪烁问题的一点经验
2015-05 由于作图过于复杂和频繁,所以时常出现闪烁的情况,一些防止闪烁的方法,如下: (1)将Invalidate()替换为InvalidateRect(). Invalidate()会导致整个 ...
- Beego 学习比较8:SQL语句
SQL语句 1> 常用的SQL语句 1->新增 insert into 表名(字段A,字段B,…) Values(字段A值,字段B值,…) 2->更新 update 表名 ...
- 自动化测试模型 Selenium IDE Selenium Gird2
1.线性测试 每个测试脚本相对独立,且不产生其他依赖与调用,其实就是单纯的来模拟用户完整的 操作场景.前一篇所写的测试脚本就属于线性测试. 优点:每个脚本完整且独立 缺点:测试用例的开发与维护成本高 ...
- 将exe和dll打包为一个exe文件
通过Nuget安装Costura.Fody 公司项目需要支持.NET 4.0(使用VS2017),Costura.Fody库从3.2.1开始支持4.0,但是不能装最新的Fody,否则会提示: Fody ...
- Spark排序方式集锦
一.简介 spark中的排序一般可以使用orderBy或sort算子,可以结合负号.ASC/DESC和col进行简单排序.二次排序等情况 二.代码实现 package big.data.analyse ...
- App的开发过程(转载)
来源:https://www.cnblogs.com/sanwenyu/p/7234616.html 不同的项目管理模式或许会有完全不同的流程步骤.但是专业性几乎是保证产品质量的唯一准则. App的开 ...