Flutter学习-网络请求
Posted GY-93
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Flutter学习-网络请求相关的知识,希望对你有一定的参考价值。
Flutter学习-网络请求
前言:项目中展示的大部分数据都是来自服务器,我们需要向服务器请求数据,并且对他们进行解析展示。
向服务器发出请求就需要用到网络请求相关的知识。
1. 网络请求的方式
在Flutter中常见的网络请求方式有三种:HttpClient、http库、dio库;
1.1 HttpClient的示例
HttpClient是dart自带的请求类,在io包中,实现了基本的网络请求相关的操作。
网络调用通常遵循如下步骤:
- 创建 client.
- 构造 Uri.
- 发起请求, 等待请求,同时您也可以配置请求headers、 body。
- 关闭请求, 等待响应.
- 解码响应的内容.
网络请求案例:
void requestNetwotk() async {
//1. 创建HttpClient的请求实例
final httpClient = HttpClient();
//2.构建请求的URI
// https://httpbin.org/get
// http://123.207.32.32:8000/api/v1/recommend
// https://httpbin.org/post
final uri = Uri.parse("https://httpbin.org/get");
//3.构建请求 返回值类型是 Future<HttpClientRequest> 是一个未来的对象,使用await之后可以使用HttpClientRequest类型来接收
HttpClientRequest request = await httpClient.getUrl(uri);//get请求
//final request = await httpClient.postUrl(uri);//post请求
//4.发送请求
HttpClientResponse response = await request.close();
//判断请求结果
if (response.statusCode == HttpStatus.ok) {
//打印成功结果
print(await response.transform(utf8.decoder).join());
} else {
print(response.statusCode);
}
}
//关闭HttpClient
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,直接在这个网站搜索:
-
dev_dependencies: 表示是开发阶段导入,打包app是不会把这下面的依赖打包进去的
-
导入并使用
void requestNeteorkThridHttp() async {
// 1.创建Client
final client = http.Client();
// 2.构建uri
final url = Uri.parse("http://123.207.32.32:8000/api/v1/recommend");
// 3.发送请求
final response = await client.get(url);
// 4.获取结果
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 {
// 1.创建Dio请求对象
final dio = Dio();
// 2.发送网络请求
final response = await dio.get("http://123.207.32.32:8000/api/v1/recommend");
// 3.打印请求结果
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);
//防止每次请求都创建一个新的Dio对象
static final Dio _dio = Dio(_baseOptions);
/**
* 参数后面的 ? 作用: 表示该参数可以为null, 如果不加? 则必须附一个默认值, 获取标记为必传参数
*/
static Future<T> request<T>(String url, {
String method = "get",
Map<String, dynamic>? params,
Interceptor? inter}) async {
//1.创建单独配置
final options = Options(method: method);
//创建一个全局的拦截器
Interceptor interceptor = InterceptorsWrapper(
onRequest: (options, handle) {
print("请求拦截");
// 1.在进行任何网络请求的时候, 可以添加一个loading显示
// 2.很多页面的访问必须要求携带Token,那么就可以在这里判断是有Token
// 3.对参数进行一些处理,比如序列化处理等
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);
//2.发送网络请求
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
方法将其进行转化
代码如下:
// 1.读取json文件
String jsonString = await rootBundle.loadString("assets/yz.json");
// 2.转成List或Map类型
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 {
// 1.读取json文件
String jsonString = await rootBundle.loadString("assets/yz.json");
// 2.转成List或Map类型
final jsonResult = json.decode(jsonString);
// 3.遍历List,并且转成Anchor对象放到另一个List中
List<Anchor> anchors = new List();
for (Map<String, dynamic> map in jsonResult) {
anchors.add(Anchor.withMap(map));
}
return anchors;
}
以上是关于Flutter学习-网络请求的主要内容,如果未能解决你的问题,请参考以下文章
VSCode自定义代码片段14——Vue的axios网络请求封装
VSCode自定义代码片段14——Vue的axios网络请求封装
VSCode自定义代码片段14——Vue的axios网络请求封装