Flutter lesson 9: Flutter的网络(HTTP)请求

Flutter中网络请求有两种,一个是使用Flutter自带的网络请求,另一种则是使用第三方HTTP请求插件dio

Flutter中自带的HTTP请求

如果要使用Flutter自带的HTTP请求,需要引入下面两个库

1
2
import 'dart:io';
import 'dart:convert';

dart:io 用于发起http请求。这个库里面才有 HttpClient

1
var httpClient = new HttpClient();

因为网络请求需要时间,我们需要在网络请求成功后在来更新数据,所以,我们需要使用到异步。Flutter 官网建议我们使用 async/await 来进行处理异步(借鉴了前端中的ES7的异步处理)。

使用Flutter自带的HTTP请求一般包含以下几个步骤:

  1. 创建 client。 new HttpClient(),这个对象下面有许多方法,get,post等等。见下图
    HttpClient 对象
  2. 构造 Uri。不同于前端(HTML)的网页请求,直接一个 URL 链接就可以了。在Flutter中,请求需要使用 Uri 而不是 Url。关于 URL 与 URI 的区别,可以HTTP 协议中 URI 和 URL 有什么区别?
  3. 发起请求,等待请求,同时您也可以配置请求的headers,body等等。
  4. 关闭请求。等待响应。
  5. 解码响应的内容。

看看下面的代码,代码来源于Flutter中文网

1
2
3
4
5
6
7
8
get() async {
var httpClient = new HttpClient();
var uri = new Uri.http(
'example.com', '/path1/path2', {'param1': '42', 'param2': 'foo'});
var request = await httpClient.getUrl(uri);
var response = await request.close();
var responseBody = await response.transform(utf8.decoder).join();
}

因为在请求中,返回的数据一般都是 JSON 格式的数据,但是在Flutter中不能直接拿出来就用,这里需要转一下,这时候就需要用到 dart:convert

使用dart:convert库可以简单解码和编码JSON。 有关其他的JSON文档,请参阅JSON和序列化

看看最后的代码,下面两个都是get,使用了不同的方式,第二个还带了参数。如果要使用post或者其他请求,可以自己尝试

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
import 'dart:io';
import 'dart:convert';

import 'package:flutter/material.dart';

void main() => runApp(LocaleHttp());

class LocaleHttp extends StatefulWidget {
LocaleHttp({Key key}) : super(key: key);

_LocaleHttpState createState() => _LocaleHttpState();
}

class _LocaleHttpState extends State<LocaleHttp> {
var data;
Map _person = {
"name": "点击按钮开始请求",
"joinTime": "点击按钮开始请求",
"email": "点击按钮开始请求"
};


_getData() async {
var url = "http://rap2api.taobao.org/app/mock/162174/common/content";
var httpClient = new HttpClient();

String result;
try {
var request = await httpClient.getUrl(Uri.parse(url));
var response = await request.close();
// 上面的两个一步执行完成后在来执行下面的判断
if( response.statusCode == HttpStatus.ok ) {
// 如果返回的状态是 200 那么请求成功
var json = await response.transform(utf8.decoder).join();
var data = jsonDecode(json);
result = data['data'][0]["description"];
}
} catch(err) {
result = "Some Error";
}

setState(() {
data = result;
});
}

_getPerson() async {
var httpClient = new HttpClient();
var uri = new Uri.http('rap2api.taobao.org', "app/mock/162174/common/get-test", {
"id": "1"
});

Map result = new Map();
setState(() {
_person = {
"name": "请求中",
"joinTime": "请求中",
"email": "请求中"
};
});
try {
var request = await httpClient.getUrl(uri);
var response = await request.close();
// 上面的两个一步执行完成后在来执行下面的判断
if( response.statusCode == HttpStatus.ok ) {
// 如果返回的状态是 200 那么请求成功
// 将返回的数据转一次格式,下面一行代码写法可以固定了
var json = await response.transform(utf8.decoder).join();
var data = jsonDecode(json)["res"];
result = data;
}
} catch(err) {
result = {
"name": "请求失败",
"joinTime": "请求失败",
"email": "请求失败"
};
}

setState(() {
_person = result;
});
}

@override
Widget build(BuildContext context) {
return Container(
child: Column(
children: <Widget>[
RaisedButton(
child: Text('获取数据'),
onPressed: _getData,
),
Text(data == null ? "空" : data),
RaisedButton(
child: Text('获取人物信息'),
onPressed: _getPerson,
),
Text(_person["name"]),
Text(_person["joinTime"]),
Text(_person["email"]),
],
),
);
}
}

上面的代码中用到了 Map 对象,注意注意的是 Map 中的对象的每一个字段的值在最开始如果已经确定好了(比如都是字符串),在后面 setState 中,如果返回的数据中有其他的数据类型(比如 number ),那这个时候你在设置的时候就会报错 type int is not a subtype of type "String"。或者你会遇到其他的错误,这个不会像在 JavaScript 中那样随意。

使用 dio

使用 dio 需要修安装 dio 插件,当前我使用的是最新的版本 2.1.11

1
2
3
4
5
6
7
dependencies:
flutter:
sdk: flutter
flutter_webview_plugin: ^0.3.5
image_picker: 0.6.0+9
fluttertoast: ^3.1.0
dio: 2.1.11

dio 具体的时候方法可以去 dio-github 上面查看,很简单,这里就不做过多说明。总之,相比于原生的 HTTP 请求,dio可谓是方便实用了需要,从下面的代码中就可以看出来。就绪在前端中,原生的 XMLHttpRequest几乎看不见,实际开发用的基本都是 axios 一样。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
import 'package:flutter/material.dart';
import 'package:dio/dio.dart';

void main() => runApp(DioHttp());

class DioHttp extends StatefulWidget {
DioHttp({Key key}) : super(key: key);

_DioHttpState createState() => _DioHttpState();
}

class _DioHttpState extends State<DioHttp> {
var data;
Map _person = {
"name": "点击按钮开始请求",
"sex": -1,
"joinTime": "点击按钮开始请求",
"email": "点击按钮开始请求"
};


_getData() async {
var url = "http://rap2api.taobao.org/app/mock/162174/common/content";
Dio dio = new Dio();

String result;
try {
Response response = await dio.get(url);
print(response.data["data"]);
// 不要使用 response.data.data[0].description 这样的形势,获取不到
result = response.data["data"][0]["description"];
} catch(err) {
result = "Some Error";
}

setState(() {
data = result;
});
}

@override
Widget build(BuildContext context) {
return Container(
child: Column(
children: <Widget>[
RaisedButton(
child: Text('获取数据'),
onPressed: _getData,
),
Text(data == null ? "空" : data)
],
),
);
}
}

具体的App的源码地址

文章作者: 踏浪
文章链接: https://blog.lyt007.cn/技术/Flutter-lesson-9-Flutter的网络(HTTP)请求.html
版权声明: 本博客所有文章除特别声明外,均采用 CC BY-NC-SA 4.0 许可协议。转载请注明来自 踏浪 - 前端技术分享
支付宝
微信打赏