一、Uri
Uri 类 提供了 编码和解码 URI(URL) 字符的功能。 这些函数处理 URI 特殊的字符,例如 &
和 =
。 Uri 类还可以解析和处理 URI 的每个部分,比如 host, port, scheme 等。
1.1.Encoding and decoding fully qualified URIs(编码解码URI)
要编码和解码除了 URI 中特殊意义(例如 /
, :
, &
,#
)的字符, 则可以使用 encodeFull()
和 decodeFull()
函数。这两个函数可以用来编码和解码整个 URI,并且保留 URI 特殊意义的字符不变。
var uri = 'http://example.org/api?foo=some message';
var encoded = Uri.encodeFull(uri);
assert(encoded ==
'http://example.org/api?foo=some%20message');
var decoded = Uri.decodeFull(encoded);
assert(uri == decoded);
注意:上面
some
和message
之间的空格被编码了。
1.2.Encoding and decoding URI components(编码解码URI组件)
使用encodeComponent()
和 decodeComponent()
可以编码 和解码 URI 中的所有字符,特殊意义的字符(/
, &
, 和:
等) 也会编码,
var uri = 'http://example.org/api?foo=some message';
var encoded = Uri.encodeComponent(uri);
assert(encoded ==
'http%3A%2F%2Fexample.org%2Fapi%3Ffoo%3Dsome%20message');
var decoded = Uri.decodeComponent(encoded);
assert(uri == decoded);
注意:上面特殊字符也被编码了,比如
/
编码为%2F
。
1.3.Parsing URIs
如果有个 Uri 对象或者 URI 字符串,使用 Uri 的属性 可以获取每个部分,比如 path
。使用 parse()
静态 函数可以从字符串中解析一个 Uri 对象:
var uri = Uri.parse('http://example.org:8080/foo/bar#frag');
assert(uri.scheme == 'http');
assert(uri.host == 'example.org');
assert(uri.path == '/foo/bar');
assert(uri.fragment == 'frag');
assert(uri.origin == 'http://example.org:8080');
1.4.Building URIs
使用 Uri()
构造函数可以从 URI 的 各个部分来构造一个 Uri 对象:
var uri = new Uri(scheme: 'http', host: 'example.org',
path: '/foo/bar', fragment: 'frag');
assert(uri.toString() ==
'http://example.org/foo/bar#frag');
更多信息参考 Uri API 文档 。
二、dart原生网络请求API
原生API使用的是用dart:io
中的HttpClient
发起的请求,但HttpClient
本身功能较弱,很多常用功能都不支持。
HTTP API 在返回值中使用了Dart Futures。 建议使用async
/await
语法来调用API。
网络调用通常遵循如下步骤:
- 1、创建 client.
- 2、构造 Uri.
- 3、发起请求, 等待请求,同时您也可以配置请求headers、 body。
- 4、关闭请求, 等待响应.
- 5、解码响应的内容.
以下示例对HTTPS GET请求返回的JSON数据进行解码:
import 'dart:async';
import 'dart:io';
import 'dart:convert'; // 使用dart:convert内置库可以简单解码和编码JSON
_getIPAddress() async {
var url = 'https://httpbin.org/ip';
// 1.创建 client.
var httpClient = new HttpClient();
// 2.构造 Uri.
var uri = Uri.parse(url);
String result;
try {
// 3.发起请求, 等待请求,同时您也可以配置请求headers、 body。
var request = await httpClient.getUrl(uri);
// 4.关闭请求, 等待响应.
var response = await request.close();
if (response.statusCode == HttpStatus.ok) {
// 5.解码响应的内容.
var json = await response.transform(utf8.decoder).join();
var data = jsonDecode(json);
result = data['origin'];
} else {
result =
'Error getting IP address:\nHttp status ${response.statusCode}';
}
} catch (exception) {
result = 'Failed getting IP address';
}
print(result); // 14.147.104.242, 14.147.104.242
三、使用第三方库http
http包含一组高级函数和类,可以方便地使用HTTP资源。它与平台无关,可以在命令行和浏览器上使用。
3.1.库的安装
- 1、在
pubspec.yaml
文件添加这个包的依赖:
dependencies:
http: ^0.12.0+2
- 2、通过命令行
pub
命令安装包
pub get
如果你装了Flutter插件也可以用以下令(也可通过用户交互界面安装,如Visual Studio Code、Android Studio装了Flutter插件):
flutter packages get
3.2.库的使用
使用这个库最简单的方法是通过顶级函数。它们允许你以最便捷的方式发出单独的HTTP请求:
import 'package:http/http.dart' as http;
var url = 'http://example.com/whatsit/create';
var response = await http.post(url, body: {'name': 'doodle', 'color': 'blue'});
print('Response status: ${response.statusCode}');
print('Response body: ${response.body}');
print(await http.read('http://example.com/foobar.txt'));
如果向同一服务器发出多个请求,可以使用Client而不是一次性请求来保持打开持久连接。如果您这样做,请确保在完成时关闭client。
var client = new http.Client();
try {
var uriResponse = await client.post('http://example.com/whatsit/create',
body: {'name': 'doodle', 'color': 'blue'});
print(await client.get(uriResponse.bodyFields['uri']));
} finally {
client.close();
}
您还可以通过自己创建Request 或StreamedRequest 对象并将其传递给Client.send来对请求和响应施加更详细的控制。
这个包被设计成可组合的。这使得外部库可以很容易地相互协作,向其添加行为。希望添加行为的库应该创建