var request = await httpClient.getUrl(Uri.parse(url));
var response = await request.close();
if (response.statusCode == HttpStatus.ok) {
var json = await response.transform(utf8.decoder).join();
var data = jsonDecode(json);
result = data[‘origin’];
print(result);
} else {
result =
‘Error getting IP address:\nHttp status ${response.statusCode}’;
}
} catch (exception) {
result = ‘Failed getting IP address’;
}
}
输出结果:122.70.159.214

二、dio

dio是一个强大的Dart Http请求库,支持Restful API、FormData、拦截器、请求取消、Cookie管理、文件上传/下载、超时、自定义适配器等

1、安装

dependencies:

dio: ^3.0.10

2、常用请求

以下实验基于Charles的MapLocal,json文件内容为{“animal”:“dog”}

- get

Response response;
Dio dio = _dio();
response = await dio.get(“http://test?id=1&name=dio1&method=get”);

// 请求参数也可以通过对象传递,上面的代码等同于:
response = await dio.get(“http://test”, queryParameters: {“id”: 2, “name”: “dio2”});

print(response.data[‘animal’]);

- post

Response response;
Dio dio = _dio();
response = await dio.post(“http://test?id=1&name=dio1&method=post”);

// 请求参数也可以通过对象传递,上面的代码等同于:
response = await dio.post(“http://test”, queryParameters: {“id”: 2, “name”: “dio2”});

print(response.data[‘animal’]);

//监听接收数据进度
response = await dio.post(
“http://test”,
queryParameters: {“id”: 2, “name”: “dio2”},
onReceiveProgress: (int receive, int total) {
print("$receive $total");
},
);

- 发起多个请求

Dio dio = _dio();
Future.wait([dio.post(“http://test/test1”), dio.get(“http://test/test2”)]).then((e) {
print(e);
}).catchError((e) {});

结果为[{“animal”:“dog”}, {“animal”:“dog”}]

- 下载文件

Dio dio = _dio();
Response response =
await dio.download(“https://www.baidu.com/”, “assets/data/test.html”);

- 上传文件

Response response;
Dio dio = _dio();
FormData formData;
formData = FormData.fromMap({
“animal”: “dog”,
});
response = await dio.post(“http/test/upload”, data: formData);

//上传多个文件
formData = FormData.fromMap({
“animal”: “dog”,
“files”: [
await MultipartFile.fromFile(“assets/data/test1.json”, filename: “test1.json”),
await MultipartFile.fromFile(“assets/data/test2.json”, filename: “test2.json”),
]
});
response = await dio.post(“http/test/upload”, data: formData);

3、配置dio

Dio dio = Dio();
// 你可以使用默认配置或传递一个可选 BaseOptions参数来创建一个Dio实例 :
// 配置dio实例
dio.options.baseUrl = “https://www.xx.com/api”;
dio.options.connectTimeout = 5000; //5s
dio.options.receiveTimeout = 3000;

// 或者通过传递一个 options来创建dio实例
BaseOptions options = BaseOptions(
baseUrl: “https://www.xx.com/api”,
connectTimeout: 5000,
receiveTimeout: 3000,
);
dio = Dio(options);

4、请求配置

BaseOptions描述的是Dio实例发起网络请求的的公共配置,而Options类描述了每一个Http请求的配置信息,每一次请求都可以单独配置,单次请求的Options中的配置信息可以覆盖BaseOptions中的配置,下面是BaseOptions的配置项:
{
/// Http method.
String method;

/// 请求基地址,可以包含子路径,如: “https://www.google.com/api/”.
String baseUrl;

/// Http请求头.
Map<String, dynamic> headers;

/// 连接服务器超时时间,单位是毫秒.
int connectTimeout;
/// 2.x中为接收数据的最长时限.
int receiveTimeout;

/// 请求路径,如果 path 以 "http(s)"开始, 则 baseURL 会被忽略; 否则,
/// 将会和baseUrl拼接出完整的的url.
String path = “”;

/// 请求的Content-Type,默认值是"application/json; charset=utf-8".
/// 如果您想以"application/x-www-form-urlencoded"格式编码请求数据,
/// 可以设置此选项为 Headers.formUrlEncodedContentType, 这样[Dio]
/// 就会自动编码请求体.
String contentType;

/// [responseType] 表示期望以那种格式(方式)接受响应数据。
/// 目前 [ResponseType] 接受三种类型 JSON, STREAM, PLAIN.
///
/// 默认值是 JSON, 当响应头中content-type为"application/json"时,dio 会自动将响应内容转化为json对象。
/// 如果想以二进制方式接受响应数据,如下载一个二进制文件,那么可以使用 STREAM.
///
/// 如果想以文本(字符串)格式接收响应数据,请使用 PLAIN.
ResponseType responseType;

/// validateStatus 决定http响应状态码是否被dio视为请求成功, 返回validateStatus
/// 返回true , 请求结果就会按成功处理,否则会按失败处理.
ValidateStatus validateStatus;

/// 用户自定义字段,可以在 [Interceptor]、[Transformer] 和 [Response] 中取到.
Map<String, dynamic> extra;

/// Common query parameters
Map<String, dynamic /String|Iterable/ > queryParameters;
}

5、响应数据

当请求成功时会返回一个Response对象,它包含如下字段:
{
/// 响应数据,可能已经被转换了类型, 详情请参考Options中的[ResponseType].
T data;
/// 响应头
Headers headers;
/// 本次请求信息
Options request;
/// Http status code.
int statusCode;
/// 是否重定向(Flutter Web不可用)
bool isRedirect;
/// 重定向信息(Flutter Web不可用)
List redirects ;
/// 真正请求的url(重定向最终的uri)
Uri realUri;
/// 响应对象的自定义字段(可以在拦截器中设置它),调用方可以在then中获取.
Map<String, dynamic> extra;
}

6、拦截器

我们可以通过继承Interceptor来实现自定义的拦截器

每个 Dio 实例都可以添加任意多个拦截器,他们组成一个队列,拦截器队列的执行顺序是FIFO。通过拦截器你可以在请求之前或响应之后(但还没有被 then 或 catchError处理)做一些统一的预处理操作。
dio.interceptors.add(InterceptorsWrapper(
onRequest:(RequestOptions options) async {
// 在请求被发送之前做一些事情
return options; //continue
// 如果你想完成请求并返回一些自定义数据,可以返回一个Response对象或返回dio.resolve(data)
// 这样请求将会被终止,上层then会被调用,then中返回的数据将是你的自定义数据data.
//
// 如果你想终止请求并触发一个错误,你可以返回一个DioError对象,或返回dio.reject(errMsg)
// 这样请求将被中止并触发异常,上层catchError会被调用。
},
onResponse:(Response response) async {
// 在返回响应数据之前做一些预处理
return response; // continue
},
onError: (DioError e) async {
// 当请求失败时做一些预处理
return e;//continue
}
));

7、拦截器中可以进行其他异步操作

dio.interceptors.add(InterceptorsWrapper(
onRequest:(Options options) async{
//…If no token, request token firstly.
Response response = await dio.get("/token");
//Set the token to headers
options.headers[“token”] = response.data[“data”][“token”];
return options; //continue
}
));

8、Lock/unlock拦截器

你可以通过调用拦截器的 lock()/unlock 方法来锁定/解锁拦截器。一旦请求/响应拦截器被锁定,接下来的请求/响应将会在进入请求/响应拦截器之前排队等待,直到解锁后,这些入队的请求才会继续执行(进入拦截器)。这在一些需要串行化请求/响应的场景中非常实用,后面我们将给出一个示例。
tokenDio = Dio(); //Create a instance to request the token.
tokenDio.options = dio.options;
dio.interceptors.add(InterceptorsWrapper(
onRequest:(Options options) async {
// If no token, request token firstly and lock this interceptor
// to prevent other request enter this interceptor.
dio.interceptors.requestLock.lock();
// We use a Dio(to avoid dead lock) instance to request token.
Response response = await tokenDio.get("/token");
//Set the token to headers
options.headers[“token”] = response.data[“data”][“token”];
dio.interceptors.requestLock.unlock();
return options; //continue
}
));
假设这么一个场景:我们需要给每个请求头中设置token,如果token不存在我们需要先请求token,获取到再继续请求,由于请求token过程是异步的,所以我们需要先锁定拦截器防止其他请求在没有获取到token的情况下进行网络请求,获取到token再解锁

9、clear()方法来清空等待队列

dio.interceptors.clear()

10、日志(开启后会打印request和response相关信息)

//由于拦截器队列的执行顺序是FIFO,如果把log拦截器添加到了最前面,则后面拦截器对options的更改就不会被打印(但依然会生效), 所以建议把log拦截添加到队尾。
dio.interceptors.add(LogInterceptor(responseBody: false)); //开启请求日志

11、DioError

{
/// Request info.
RequestOptions request;

/// Response info, it may be null if the request can’t reach to
/// the http server, for example, occurring a dns error, network is not available.
Response response;

/// 错误类型,见下文
DioErrorType type;

///原始的error或exception对象,通常type为DEFAULT时存在。
dynamic error;
}

enum DioErrorType {
///

It occurs when url is opened timeout.
CONNECT_TIMEOUT,

/// It occurs when url is sent timeout.
SEND_TIMEOUT,

///It occurs when receiving timeout.
RECEIVE_TIMEOUT,

/// When the server response, but with a incorrect status, such as 404, 503…
RESPONSE,

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

/// Default error type, Some other Error. In this case, you can
/// read the DioError.error if it is not null.
DEFAULT
}

12、CancelToken,取消请求

CancelToken token = CancelToken();
dio.post("/testpost?id=1&name=dio1&method=post",cancelToken: token).catchError((e) {
//我们会发现CancelToken提供了错误类型的判断,即此时CancelToken.isCancel(err)是true
//如
if (CancelToken.isCancel(err)) {
print(“被取消啦”);
}

}).then((data) {
return data;
});
token.cancel();

cancel_token.dart中源码也是判断DioErrorType
static bool isCancel(DioError e) {
return e.type == DioErrorType.CANCEL;
}

13、dio和HttpClient关系

HttpClientAdapter是 Dio 和 HttpClient之间的桥梁。2.0抽象出adapter主要是方便切换、定制底层网络库。Dio实现了一套标准的、强大API,而HttpClient则是真正发起Http请求的对象。我们通过HttpClientAdapter将Dio和HttpClient解耦,这样一来便可以自由定制Http请求的底层实现,比如,在Flutter中我们可以通过自定义HttpClientAdapter将Http请求转发到Native中,然后再由Native统一发起请求。再比如,假如有一天OKHttp提供了dart版,你想使用OKHttp发起http请求,那么你便可以通过适配器来无缝切换到OKHttp,而不用改之前的代码。 Dio 使用DefaultHttpClientAdapter作为其默认HttpClientAdapter,DefaultHttpClientAdapter使用dart:io:HttpClient 来发起网络请求。

扩展(适配器模式) 首页定义接口,接口中对要实现的功能加以抽象,然后定义不同的Adapter类来实现这个接口,Adapter类中是对接口中方法的不同实现,上层的调用代码不需要改变就可以随意切换对底层不同的功能调用。

14、设置代理

DefaultHttpClientAdapter 提供了一个onHttpClientCreate 回调来设置底层 HttpClient的代理,我们想使用代理,可以参考下面代码:
import ‘package:dio/dio.dart’;
import ‘package:dio/adapter.dart’;

(dio.httpClientAdapter as DefaultHttpClientAdapter).onHttpClientCreate = (client) {
// config the http client
client.findProxy = (uri) {
//proxy all request to localhost:8888
return “PROXY localhost:8888”;
};
// you can also create a HttpClient to dio
// return HttpClient();

如果你进阶的路上缺乏方向,可以加入我们的圈子和安卓开发者们一起学习交流!

  • Android进阶学习全套手册

  • Android对标阿里P7学习视频

  • BATJ大厂Android高频面试题

最后,借用我最喜欢的乔布斯语录,作为本文的结尾:

人这一辈子没法做太多的事情,所以每一件都要做得精彩绝伦。
你的时间有限,所以不要为别人而活。不要被教条所限,不要活在别人的观念里。不要让别人的意见左右自己内心的声音。
最重要的是,勇敢的去追随自己的心灵和直觉,只有自己的心灵和直觉才知道你自己的真实想法,其他一切都是次要。
起学习交流!**

  • Android进阶学习全套手册

    [外链图片转存中…(img-YFvJGnEM-1647529250960)]

  • Android对标阿里P7学习视频

    [外链图片转存中…(img-BwAuHTYw-1647529250960)]

  • BATJ大厂Android高频面试题

    [外链图片转存中…(img-B0II1L7E-1647529250961)]

最后,借用我最喜欢的乔布斯语录,作为本文的结尾:

人这一辈子没法做太多的事情,所以每一件都要做得精彩绝伦。
你的时间有限,所以不要为别人而活。不要被教条所限,不要活在别人的观念里。不要让别人的意见左右自己内心的声音。
最重要的是,勇敢的去追随自己的心灵和直觉,只有自己的心灵和直觉才知道你自己的真实想法,其他一切都是次要。

Flutter网络请求库DIO入门文档,实战案例相关推荐

  1. Flutter网络请求库DIO入门文档(1),android开发网

    }); response = await dio.post("http/test/upload", data: formData); //上传多个文件 formData = For ...

  2. Flutter网络请求库DIO的使用

    1. 导入dio包 目前dio库的最新版本是3.0.1,同使用其他三方库一样,Flutter中使用dio库同样需要配置pubspec.yaml文件. dependencies:flutter:sdk: ...

  3. Flutter实战之网络请求框架Dio入门使用

    本篇博文涉及到的demo很简单,就是通过调用天气查询接口来显示城市的天气信息.通过本demo可以了解: 1.CityPicker的简单使用 2.Dio网络请求库的简单使用 3.Flutter对json ...

  4. Flutter 网络请求框架dio使用详解

    前言 dio是一款Flutter 网络请求框架,在GitHub上目前有超过5.9k个star.由国人(Flutter中文网)开发,所以中文文档非常完善. 这里copy了dio官方的文档,便于自己开发时 ...

  5. Flutter 网络请求库http

    http 集成http库 https://pub.dartlang.org/packages/http 添加依赖 dependencies:http: ^0.12.0 安装 flutter packa ...

  6. PHP 的 cURL库快速入门文档

    作者:Burak Guzel 原文链接:http://net.tutsplus.com/tutorials/php/techniques-and-resources-for-mastering-cur ...

  7. flutterdio_强大的Flutter http请求库dio

    dio是Flutter中文网开源的一个强大的Dart Http请求库,支持Restful API.FormData.拦截器.请求取消.Cookie管理.文件上传/下载.超时等... 自dio开源至今, ...

  8. 吕文翰 php,自己动手写一个 iOS 网络请求库(三)——降低耦合

    自己动手写一个 iOS 网络请求库(三)--降低耦合 2015-5-22 / 阅读数:16112 / 分类: iOS & Swift 本文中,我们将一起降低之前代码的耦合度,并使用适配器模式实 ...

  9. Android入门文档

    该文章为网络材料整理,部分内容经过重新编写. 一. 名词介绍 JDK:Java Development Kit Java 语言的软件开发工具包 JRE:Java Runtime Environment ...

最新文章

  1. C# Unity编程终极指南
  2. iOS lldb调试
  3. python全栈开发第36天------GIL全局解释锁、死锁现象和递归锁、信号量、Event事件、线程...
  4. 在JDK 8中连接字符串
  5. Linux之GDB调试命令
  6. windows怎么将图片变为单色图片_印刷丨单色黑与四色黑
  7. 计算机考研要过六级吗,本科考研英语过几级 有四六级要求吗
  8. bex5 mysql_BeX5开发中MySQL视图使用的一个小问题
  9. 网页设计与制作(HTML+CSS)
  10. java font 字体大小_java的字体的颜色,型号,大小的方法
  11. 2021年N1叉车司机考试及N1叉车司机考试试卷
  12. 一款不错的手机端视频剪辑软件
  13. 鸿蒙系统电脑适配双面打印机,win10系统实现打印机双面打印的操作方法
  14. 一个数和0xFFFF与运算的意义
  15. bind9 dlz mysql_bind9+dlz+mysql连接断开问题
  16. excel批量改名字(含识别区分)
  17. ArcGIS 切片缓存紧凑文件格式分析与使用
  18. 将SoundCloud API与Jav​​aScript SDK结合使用
  19. B站兄弟连Linux视频笔记
  20. 解决Ubuntu更新后无线网卡不能使用的问题

热门文章

  1. 领略千变万化的Android Drawable (二)
  2. 【虚幻引擎UE】UE5 阴影异常与优化
  3. 移动通信技术发展历程及未来趋势
  4. 福利来了!教你们怎么把整个网站的漂亮小姐姐视频都给爬下来!
  5. HTML字体以及图标字体iconfont、Font Awesome的使用
  6. C语言strtok函数的用法
  7. 计算机二级补录成绩,成考没考过怎么办有补录机会吗
  8. 2021年北京旅游行业发展现状分析:接待旅游总人数达2.6亿人次,同比增长41.3%。[图]
  9. 销售人员应关注的 5 个指标
  10. vue 动态获取的图片路径不显示_Vue 动态图片加载路径问题和解决方法