前言:项目中展示的大部分数据都是来自服务器,我们需要向服务器请求数据,并且对他们进行解析展示。 向服务器发出请求就需要用到网络请求相关的知识。
1. 网络请求的方式
在Flutter中常见的网络请求方式有三种:HttpClient、http库、dio库;
1.1 HttpClient的示例
HttpClient是dart自带的请求类,在io包中,实现了基本的网络请求相关的操作。
网络调用通常遵循如下步骤:
- 创建 client.
- 构造 Uri.
- 发起请求, 等待请求,同时您也可以配置请求headers、 body。
- 关闭请求, 等待响应.
- 解码响应的内容.
网络请求案例:
void requestNetwotk() async {
final httpClient = HttpClient();
final uri = Uri.parse("https://httpbin.org/get");
HttpClientRequest request = await httpClient.getUrl(uri);
HttpClientResponse response = await request.close();
if (response.statusCode == HttpStatus.ok) {
print(await response.transform(utf8.decoder).join());
} else {
print(response.statusCode);
}
}
httpClient.close();
- 代码分析:
- 新建
HttpClient 对象,通过 getUrl方法获取 HttpClientRequest - 通过
HttpClientRequest.close() ,发起Http 请求, 获取 HttpClientResponse - 判断请求结果根据code码,
response.statusCode 来判断 HttpClientResponse 是一个Stream 对象,通过Utf8Decoder 解码,然后join 操作符转换成String 对象,可以打印出HttpClientResponse 的字符串。- 关闭
HttpClient 
HttpClient虽然可以发送正常的网络请求,但是会暴露过多的细节:
- 比如需要主动关闭request请求,拿到数据后也需要手动的进行字符串解码
- 在开发中,我们一般很多直接面向
HttpClient 进行网络请求并不是直接使用HttpClient ,而是使用一些库来完成
注意:HttpClient其中还有很多知识,如果大家需要深入了解HttpClient,建议大家多看文档,多找资料学习
1.2 Http库
http 是 Dart 官方 提供的另一个网络请求类,相比于 HttpClient,易用性提升了不少。
但是,没有默认集成到Dart的SDK中,所以我们需要先在pubspec 中依赖它:
大家如果需要找第三方库:https://pub.dev,直接在这个网站搜索: 


void requestNeteorkThridHttp() async {
final client = http.Client();
final url = Uri.parse("http://123.207.32.32:8000/api/v1/recommend");
final response = await client.get(url);
if (response.statusCode == HttpStatus.ok) {
print(response.body);
} else {
print(response.statusCode);
}
}
1.3 dio三方库
官方提供的HttpClient和http都可以正常的发送网络请求,但是对于现代的应用程序开发来说,我们通常要求的东西会更多:比如拦截器、取消请求、文件上传/下载、超时设置等等; 这个时候,我们可以使用一个在Flutter中非常流行的三方库:dio; 官网有对dio进行解释:
dio是一个强大的Dart Http请求库,支持Restful API、FormData、拦截器、请求取消、Cookie管理、文件上传/下载、超时、自定义适配器等…
使用dio三方库必然也需要先在pubspec中依赖它: 
dio代码简单演练:
import 'package:dio/dio.dart';
void dioNetwork() async {
final dio = Dio();
final response = await dio.get("http://123.207.32.32:8000/api/v1/recommend");
if (response.statusCode == HttpStatus.ok) {
print(response.data);
} else {
print("请求失败:${response.statusCode}");
}
}
1.4 dio库的简单封装
建议大家在使用三方库的时候,必须要自己封装一层,防止后期三方库弃用和更换别的三方库,导致程序改动困难
更对并且具体的使用方法参考github上的源码和文档:https://github.com/flutterchina/dio
import 'package:dio/dio.dart';
class HttpConfig {
static const String baseUrl = "https://httpbin.org";
static const int timeOut = 5000;
}
class HttpRequest {
static final BaseOptions _baseOptions = BaseOptions(baseUrl: HttpConfig.baseUrl,connectTimeout: HttpConfig.timeOut);
static final Dio _dio = Dio(_baseOptions);
static Future<T> request<T>(String url, {
String method = "get",
Map<String, dynamic>? params,
Interceptor? inter}) async {
final options = Options(method: method);
Interceptor interceptor = InterceptorsWrapper(
onRequest: (options, handle) {
print("请求拦截");
return;
},
onResponse: (response, handle) {
print("响应拦截");
return;
},
onError: (err, handle) {
print("错误拦截");
return;
}
);
List<Interceptor> inters = [interceptor];
if (inter != null) {
inters.add(inter);
}
_dio.interceptors.addAll(inters);
try {
Response response = await _dio.request(url,queryParameters: params,options: options);
return response.data;
} on DioError catch(e) {
return Future.error(e);
}
}
}
使用:
HttpRequest.request("/get",method: "get",params: {"name":"gwy"}).then((value) {
print("请求数据回来=========$value");
});
2. JSON的读取和解析
在开发中,我们经常会使用本地JSON或者从服务器请求数据后回去到JSON,拿到JSON后通常会将JSON转成Model对象来进行后续的操作,因为这样操作更加的方便,也更加的安全。 所以学习JSON的相关操作以及读取JSON后如何转成Model对象对于Flutter开发也非常重要。
2.1 本地JSON资源配置
JSON也属于一种资源,所以在使用之前需要先进行相关的配置,配置本地JSON文件和之前我们配置本地图片一样

2.2 JSON数据的读取解析
JSON资源读取
如果我们希望读取JSON资源,可以使用package:flutter/services.dart 包中的rootBundle 。
在rootBundle 中有一个loadString 方法,可以去加载JSON资源
- 但是注意,查看该方法的源码,你会发现这个操作是一个异步的
Future<String> loadString(String key, { bool cache = true }) async {
...省略具体代码,可以自行查看源码
}
代码如下:
import 'package:flutter/services.dart' show rootBundle;
rootBundle.loadString("assets/yz.json").then((value) => print(value));
JSON字符串转化
拿到JSON字符串后,我们需要将其转成成我们熟悉的List和Map类型。 我们可以通过dart:convert 包中的json.decode 方法将其进行转化
代码如下:
String jsonString = await rootBundle.loadString("assets/yz.json");
final jsonResult = json.decode(jsonString);
对象Model定义 将JSON转成了List和Map类型后,就可以将List中的一个个Map转成Model对象,所以我们需要定义自己的Model
class Anchor {
String nickname;
String roomName;
String imageUrl;
Anchor({
this.nickname,
this.roomName,
this.imageUrl
});
Anchor.withMap(Map<String, dynamic> parsedMap) {
this.nickname = parsedMap["nickname"];
this.roomName = parsedMap["roomName"];
this.imageUrl = parsedMap["roomSrc"];
}
}
2.3 JSON解析代码
完整解析逻辑代码:
import 'package:flutter/services.dart' show rootBundle;
import 'dart:convert';
import 'dart:async';
class Anchor {
String nickname;
String roomName;
String imageUrl;
Anchor({
this.nickname,
this.roomName,
this.imageUrl
});
Anchor.withMap(Map<String, dynamic> parsedMap) {
this.nickname = parsedMap["nickname"];
this.roomName = parsedMap["roomName"];
this.imageUrl = parsedMap["roomSrc"];
}
}
Future<List<Anchor>> getAnchors() async {
String jsonString = await rootBundle.loadString("assets/yz.json");
final jsonResult = json.decode(jsonString);
List<Anchor> anchors = new List();
for (Map<String, dynamic> map in jsonResult) {
anchors.add(Anchor.withMap(map));
}
return anchors;
}
|