这里主要分享我对于Flutter网络请求方面的内容
目的
目的很简单,需要完成项目中常规的Http的GET和POST请求服务端接口数据以完成页面部分展示逻辑
方案
主要实现方案有三种,一种是基于原生的HttpClient来实现,另外两种是基于第三方package来实现:http与dio
httpClient
原生方式主要基于dart:io库中的httpClient来实现:
import 'dart:io';
var httpClient = new HttpClient();
该 client 支持常用的HTTP操作, such as GET, POST, PUT, DELETE.
核心步骤主要包括:
- 创建 client.
- 构造 Uri.
- 发起请求, 等待请求,同时您也可以配置请求headers、 body。
- 关闭请求, 等待响应.
- 解码响应的内容.
而response中需要基于Futuers来实现(同时配合await/async函数),类似于JS的Promise:
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();
}
拿到的response若希望以JSON格式进行解析,通常还需要借助dart:convert库中的方法:
Map data = JSON.decode(responseBody);
// 假设返回体结构类似:['foo', { 'bar': 499 }]
int barValue = data[1]['bar']; // bar Value 设置为 499
OK,以上就是该方案的简单使用方法了
http库
该库的地址在:https://pub.flutter-io.cn/packages/http
简单来说该库简化了Http的相关操作,具体使用方式和教程上面的链接都有,这里贴一个简单示例
import 'package:http/http.dart' as http;
var url = Uri.parse('https://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(Uri.parse('https://example.com/foobar.txt')));
我的项目比较简单,最后用该库作为网络请求的API了
dio库
这个名字贼霸气的库地址在:https://pub.flutter-io.cn/packages/dio
该库封装了httpClient的使用并且支持拦截器,全局配置,数据格式化,请求Cancel,文件下载等更多功能
建议大家在实际项目可以优先选用,库的文档和网上教程也很多,不容易遇到坑
最后在补充一个简体的文档: https://github.com/flutterchina/dio/blob/master/README-ZH.md
import 'package:dio/dio.dart';
void getHttp() async {
try {
var response = await Dio().get('http://www.google.com');
print(response);
} catch (e) {
print(e);
}
}
遇到的问题
网络请求开发过程中还遇到过两个小问题,排除后目前都解决了,也跟大家一起分享一下
Socket Exception 异常
在第一次真机测试时,log报了类似如下的错误:
[ERROR:flutter/lib/ui/ui_dart_state.cc(199)] Unhandled Exception: DioError [DioErrorType.other]: SocketException: OS Error: Connection timed out, errno = 110, address = 192.168.xxx.xxx, port = xxxx
我一开始没仔细看Log,以为是库的使用有问题,但是切换到原生库还是报了类似的问题,核心都是SocketException和连接超时
但是试了一下真机是可以联网的啊,并且也试了网上将测试的Host从localhost改为实际IP(本地接口测试开发ing),也没用
最后发现是因为主机的网络和真机的网络不在同一个局域网下导致的,因为你电脑连接真机调试后就会走电脑代理,最后调整了一下真机的IP解决了~
返回的数据包含中文乱码
另一个问题是我的测试数据包含中文字符,但是res并且decode后拿到的是中文乱码,第一时间想到可能是decode时字符编码没有选对,导致对应的字符没找到。
后面看了下http和jsonDecode的文档,发现需要提前用utf-8解码一下:
final res = json.decode(utf8.decode(response.bodyBytes))
OK,解决了
回顾
- 三种Flutter网络请求的实现方式
- 真机测试时报Socket Exception的一种解决方案
- 返回部分中文数据是乱码的原因和解决方案
|