在项目开发过程中,发送网络请求获取数据是避免不了的需求,今天我们来讲解一下Flutter中的网络请求如何发送;

网络请求

Flutter中,发送网络请求一般会用到两个库:

  • http(官方的)

image.png

image.png
今天我们先使用官方的http发送网络请求;

配置网络请求库

首先进入http的地址:https://pub.dev/packages/http,网页内容如下:
image.png
点击图片中红框所示的按钮进行复制操作:
image.png
可以看到,我们拷贝了一串字符串:

  1. http: ^0.13.4

那么,这个字符串有什么用呢?打开工程的pubspec.yaml文件,找到红框所示区域:
image.png
注意不要找错区域;

我们发现,在红框区域中,cupertina_icons: ^1.0.2跟我们刚才复制的http: ^0.13.4格式一模一样了;在此处配置的就是我们需要用到的一些库,我们将http的配置信息添加进去,该操作类似iOSCocoaPods的用法:
image.png
然后点击图中箭头所示的Pub get按钮,控制台输入如下信息即为载入成功,我们就可以使用http库了:
image.png

网络请求库的使用

我们已经将http载入成功,那么如何使用呢?首先,我们需要在使用http的页面,引入http,引入代码如下:

  1. import 'package:http/http.dart' as http;

然后我们定义一个方法来请求数据,并且在initState中调用该方法:

  1. @override
  2. void initState() {
  3. super.initState();
  4. // 发送网络请求
  5. getConversationList();
  6. }
  7. getConversationList() {
  8. }

但是需要注意的是,我们在getConversationList方法中发送网络请求,那么很明显,该方法应该是异步执行的,不能影响其他代码的执行,所以我们需要给getConversationList方法添加异步的标识:

  1. getConversationList() async {
  2. }

http发送请求

接下来就是放松网络请求了,http发送网络请求方式如下:
image.png
需要注意的是,get()是放松了一个Get方式的网络请求,其方法定义如下:

  1. Future<Response> get(Uri url, {Map<String, String>? headers}) =>
  2. _withClient((client) => client.get(url, headers: headers));

可以看到,该方法是有返回值的;我们在开发iOS项目中,发送网络请求,请求的结果数据一般都是通过block回调返回;但是在Flutterhttp网络请求中,数据方法的直接返回值,而get()很明显应该是异步请求,所以我们需要使用await标记一下:
image.png
我们打印一下看看网络请求的结果:
image.png

解析数据

我们已经从服务器获取到了数据,接下来就是解析数据:
image.png

  1. List<Chat> chatList = responseBody['chat_list'].map<Chat>((item) => Chat.formMap(item)).toList();

这句代码的意思是:从responseBody中取出chat_list这个数组,然后map方法将会循环遍历此数组,遍历的元素为item,将item通过Chat.fromMap方法转换成Chat模型数据,最终toList()意为将所有的转换之后的Chat放进数组中,返回一个List

我们来看一下打印结果:
image.png

异步方法返回值

在以往iOS的开发中,网络请求的数据,经过方法的处理之后,我们通常通过block的形式跑出来,那么在Flutter中,异步的方法能够接收返回值呢?答案当然是可以的,我们需要将方法作如下修改:
image.png

Future来接收返回值;表示这是一个未来的数据;

接下来看一下,getConversationList方法的返回值是如何处理的:
image.png
也可以使用链式调用:

  1. getConversationList().then((value) {
  2. print('===$value');
  3. });

我们看一下打印结果:
image.png

网络请求的处理

我们已经知道在then中能够获取到网络请求的数据,那么是否还有其他状态的处理呢?

  • 错误处理

catchError用来捕获错误信息;
image.png

  • 请求完成

whenComplete在网络请求完成时回调;
image.png

  • 设置超时时间

timeout可以设置网络请求的超时时间;
image.png
我们将超时时间设置为1毫秒,看一下打印信息:
image.png
我们发现,即使网络请求超时了,但是thenwhenComplete的回调依然执行了,这是因为在Flutter中即使只要网络请求发出,那么就一定会有结果,而结果的状态需要我们自己去控制,比如通过自定义的bool值:

dio发送请求

dio是国内的大神开发的请求框架,我们后续再细讲;
想研究的,可以前往dio使用

模型转换

我们的网络请求返回的数据一般是json格式的,那么我们如果将json字符串转换成模型数据呢?

Map转json

引入头文件:

  1. import 'dart:convert';

引入头文件之后,可直接使用json调用encode方法转换;

json转map方式如下:

  1. final map = {'name': '张三','age': '30','nickName': '法外狂徒',};
  2. final jsonStr = json.encode(map);
  3. print('map: $map');
  4. print('json: $jsonStr');
  • json:调用者,引入头文件之后可直接使用;
  • mapMap类型数据;
  • jsonStr:转换之后的json字符串;

打印结果:

  1. flutter: map: {name: 张三, age: 30, nickName: 法外狂徒}
  2. flutter: json: {"name":"张三","age":"30","nickName":"法外狂徒"}

json转Map

  1. final newMap = json.decode(jsonStr);
  2. print('new: $newMap');
  • json:调用者,引入头文件之后可直接使用
  • jsonStr:需要转换的json字符串;
  • newMap:转换之后的Map类型数据;

打印结果:

  1. flutter: new: {name: 张三, age: 30, nickName: 法外狂徒}

json转模型

我们先定义一个Chat的模型数据,格式如下:

  1. class Chat {
  2. final String? name;
  3. final String? message;
  4. final String? avatar;
  5. Chat({this.name, this.message, this.avatar});
  6. factory Chat.formMap(Map map) {
  7. return Chat(
  8. name: map['name'],
  9. message: map['message'],
  10. avatar: map['avatar']
  11. );
  12. }
  13. }
  • factory:工厂构造,可以定义构造方法的返回值;

转换方式如下:

  1. final map = {'name': '张三','message': '你好','avatar': 'https://randomuser.me/api/portraits/men/21.jpg',};
  2. final chat = Chat.formMap(map);
  3. print('name:${chat.name}; avatar:${chat.avatar}; message:${chat.message}');

打印结果:

  1. flutter: name:张三; avatar:https://randomuser.me/api/portraits/men/21.jpg; message:你好