前面讲完了常用的部件,BLoC 模式,数据持久化等常用的,今天再介绍个重头戏 —— 网络请求
HttpClient
HttpClient 是 dart 自带的网络请求方式,在 dart:io 包下。使用 HttpClient 作为请求分以下几个步骤
创建 HttpClient 实例
1
HttpClient client = HttpClient();
打开连接,并设置一些头参数,请求参数等
1
2
3
4
5
6
7
8
9
10
11
12// 如果 url 中没有查询参数可直接创建
Uri uri = Uri.parse('https://www.xxx.com');
// 如果存在查询参数则在 Uri 中添加
Uri uri = Uri(scheme: 'https', host: 'www.xxx.com', queryParameters: {'a': 'AAA'});
// 打开连接
HttpClientRequest request = await client.getUrl(uri);
request.headers.add('token', 'Bear ${'x' * 20}'); // 添加头部 token 信息
// 如果是 post 或者 put 请求,通过 `add` 添加请求体
// 因为 `add` 方法需要传入 `List<int>` 参数,可以通过 utf8.encode 进行编码
request.add(utf8.encode('{"a": "aaa"}'));
// 也可以通过添加流的方式进行添加
request.addStream(input);连接服务器
1
2
3// 设置 request 后通过 request.close() 获取一个响应对象 HttpClientResponse,
// 包括响应头,响应内容等
HttpClientResponse response = await request.close();读取服务器响应内容
1
String responseBody = await response.transform(utf8.decoder).join();
关闭实例
1
client.close();
例如我们要去请求 Bird.so 的首页并显示,我们可以这么实现
1  | _httpClientRequest() async {  | 
最后实现的效果

很显然,用 HttpClient 请求相对来说是个非常麻烦的过程,如果要涉及到文本上传之类的,那么就会更麻烦了,所以这边引入一个网络请求的插件 dio,写本文的时候版本为 2.1.0
Dio
dio 是个非常强大的网络请求库,他的方式类似 OkHttp,我们可以直接查看官方文档,使用方式非常简单,创建一个 Dio 实例,然后就可以通过 get,post 等方式发起请求,返回 Future<Response>,而且支持多个并发请求,可以设置返回响应的类型,监听上传下载进度等等,看着就很给力。对于简单的方式,这边就不做太多介绍,主要讲下拦截器,也是非常给力的一部分。比如我们需要请求这么个接口 https://randomuser.me/api/

这个接口通过 get 请求,可以加入任意的查询参数。比如我们需要实现一个请求加解密的过程,如果每次都在上传参数或者返回请求的时候去加密,解密的话,就做了非常多无用功了,那么这时候拦截器就派上用场了。先定义下加解密的规则,上传的参数统一转为小写,不存在大写,请求回的数据,不能含有 info 字段。看下如何实现
1  | _dioRequest() async {  | 
看下最后的显示信息


请求体的头部成功加上了 authorization 参数,请求的参数全部变为小写,返回的信息也把 info 字段值去除。在很多时候,请求接口后,需要将 json 转换成 pojo 类来处理,可以通过 json_serializable 这个三方插件实现,这边提供文章 Flutter Json自动反序列化,当然这种方式比较麻烦,这里推荐个 Android Studio 下的插件 dart_json_format 直接搜索就可以,如果用的是 Vitual Code 或者别的不是 JetBrains 系列的,这里有个转换的网址 JsonToDart。
以上代码查看 http_main.dart 文件
实践一下下
不知道小伙还记得前面讲的 BLoC 没有,忘了可以查看 Flutter 状态管理及 BLoC,这里结合 BLoC 和 Dio 实现界面和逻辑分离的小例子,接口使用前面提到的 https://randomuser.me/api/ 接口。网络应该是比较常用的,所以对其进行一些封装还是很有必要的,这边提供下我自己封装的方法
1  | import 'package:dio/dio.dart';  | 
封装后就可以愉快的调用了,如果有别的请求方式后期可以继续扩展。继续看代码,创建一个 application.dart 文件,用于存放全局参数
1  | class Application {  | 
并在 main() 方法中进行初始化,接下来就可以直接使用
1  | void main() {  | 
看下最后的实现效果吧,刚进入没有数据则通过转圈圈提示,加载完数据后,点击头像更换下个

实现 BLoC 需要有一个管理类
1  | class UserBloc extends BaseBloc {  | 
设置好管理类后,就可以来编写界面了,界面也比较简单
1  | class UserPageDemo extends StatelessWidget {  | 
以上代码查看 bloc_network 包下的所有文件