dio 是dart 开源的网络库 ,基于dart语言 。使用简单,性能稳定 。
一.dio的架构
执行流:
请求拦截器 >> 请求转换器 >> 发起请求 >> 响应转换器 >> 响应拦截器 >> 最终结果。
支持的功能:
http、FormData、拦截器、请求取消、Cookie管理、文件上传/下载、超时、错误处理、转换器、代理。
二、 开始实验
1. 引入包
知识点:
1.flutter有自己的包管理仓库 Pub
- flutter可以引入 pub包,本地路径包,git包 ,github包
- flutter核心库不包含颜色,要使用 css_colors 第三方库
- 要使用浏览器 要参考 url_launcher第三方库
使用方法:
1.打开 pubspec.yaml 文件,然后在dependencies下添加dio: 2.1.x (表示最新版)
- 终端运行
flutter packages get
3.在main.dart中引入开始使用
三.dio的使用
1. 自己准备一个服务器接口 。(有接口的跳过不用自己搭建一个服务器了)
这里我是用swift语言自己在本机搭建一个PerfectSwift
不愿意研究的可以直接下面,有时间了写一个完整的swift服务器的教程
注:【】中表示输入的命令
bogon:~ home$ 【 mkdir /Users/chaoshen/SwiftServer 】
bogon:~ home$ 【 cd /Users/chaoshen/SwiftServer 】
bogon:SwiftServer home$ 【 git clone https://github.com/PerfectlySoft/PerfectTemplate.git】
Cloning into 'PerfectTemplate'...
remote: Enumerating objects: 275, done.
remote: Total 275 (delta 0), reused 0 (delta 0), pack-reused 275
Receiving objects: 100% (275/275), 60.50 KiB | 160.00 KiB/s, done.
Resolving deltas: 100% (137/137), done.
bogon:SwiftServer home$ 【 cd PerfectTemplate 】
bogon:PerfectTemplate home$ 【 swift build】
省略编译信息
bogon:PerfectTemplate home$【 .build/debug/PerfectTemplate】
[INFO] Starting HTTP server localhost on :::8181#表示启动了
成功之后浏览器输入http://127.0.0.1:8181/
有界面出现就是成功了。 PerfectTemplate/main.swift 更改文件可以更改接口
终端【ctrl + c】 停止运行
进入目录查看一下
如果你是用xcode开发 ,随意位置建立一个文件夹 【cd】/终端【swift package generate-xcodeproj
】,建立一个server服务器项目一直使用xcode写就可以了。
vccode 写app xcode写服务器是不是不要太爽啊
holle world是个页面web接口 。业务接口返回json那种怎么写 。
将下面代码覆盖main.swift,重新启动服务器接口就可以请求了。
如果你不了解服务器编写/ 现在还不建议你用xcode编写,因为会有大坑,每次增加文件或者删除文件都要重新编译,【打包】Xcode工程
2. 删除test文件夹 以及里面的文件 ,删除 main.dart的所有内容 ,写一个简单的例子运行一下
2.1get接口获取
import 'package:dio/dio.dart';
void main() => getHttp(); ##主函数入口
void getHttp() async { ## 异步处理
try { ##不崩溃处理
Response response = await
Dio().get("http://192.168.1.107:8181/getDatas");
print("我很帅" + response.toString());
} catch (e) {
print("我不帅" + e.toString());
}
}
2.2post接口获取
import 'package:dio/dio.dart';
void main() => getHttp(); ##主函数入口
void getHttp() async { ## 异步处理
try { ##不崩溃处理
Response response = await
Dio().post("http://192.168.1.107:8181/getDatas",data:{"id":12,"name":"wendu"});
print("我很帅" + response.toString());
} catch (e) {
print("我不帅" + e.toString());
}
}
2.3 多个接口
future 参见文章
response= await Future.wait([dio.post("/mobile"),dio.get("/token")]);
2.4 下载文件
我们下载一张图片试试
import 'dart:async';
import 'dart:io';
import 'package:dio/dio.dart';
// In this example we download a image and listen the downloading progress.
main() async {
var dio = new Dio();
dio.interceptors.add(LogInterceptor());
// This is big file(about 200M)
// var url = "http://download.dcloud.net.cn/HBuilder.9.0.2.macosx_64.dmg";
var url =
"https://cdn.jsdelivr.net/gh/flutterchina/[email protected]/docs/imgs/book.jpg";
// var url = "https://www.baidu.com/img/bdlogo.gif";
// await download1(dio, url, "./example/book1.jpg");
await download1(dio, url, (HttpHeaders headers)=>"./example/book1.jpg");
//await download2(dio, url, "./example/book2.jpg");
}
Future download1(Dio dio, String url, savePath) async {
try {
await dio.download(
url,
savePath,
onReceiveProgress: showDownloadProgress,
);
} catch (e) {
print(e);
}
}
Future download2(Dio dio, String url, String savePath) async {
try {
Response response = await dio.get(
url,
onReceiveProgress: showDownloadProgress,
//Received data with List
options: Options(
responseType: ResponseType.bytes,
followRedirects: false,
),
);
print(response.headers);
File file = new File(savePath);
var raf = file.openSync(mode: FileMode.write);
// response.data is List type
raf.writeFromSync(response.data);
await raf.close();
} catch (e) {
print(e);
}
}
void showDownloadProgress(received, total) {
if (total != -1) {
print((received / total * 100).toStringAsFixed(0) + "%");
}
}
2.5 后面都尝试一下可以干什么
四. json字符串的反序列化
1.中文官网介绍
注意:
使用 dart:convert ,flutter 禁止运行时反射
- 单个无依赖的model 可以使用 JSON.decode()
class User {
final String name;
final String email;
User(this.name, this.email);
User.fromJson(Map json)
: name = json['name'],
email = json['email'];
Map toJson() =>
{
'name': name,
'email': email,
};
}
调用
Map userMap = JSON.decode(json);
var user = new User.fromJson(userMap);
print('Howdy, ${user.name}!');
print('We sent the verification link to ${user.email}.');
- 一个User.fromJson 构造函数, 用于从一个map构造出一个 User实例 map structure
- 一个toJson 方法, 将 User 实例转化为一个map.
2. 在大中型项目中使用代码生成, 例如,json_serializable和built_value这样的库。
我们以 json_serializable 为例子来研究,引入包
json_serializable package
2.1 引入
需要在pubspec.yaml
添加三个依赖,它们分别是:"son_annotation
" "build_runner
" 和 "json_serializable
"。
dependencies:
# Your other regular dependencies here
json_annotation: '>=2.1.0 <2.3.0' # json反序列化json_serializable需要
dev_dependencies:
# Your other dev_dependencies here
build_runner: ^1.0.0 # #创建.g.dart json反序列化json_serializable需要
json_serializable: '2.1.0 <2.3.0' # json反序列化json_serializable需要
注意yaml文件的缩进要求很严格,与python类似
2.2 环境配置
根目录运行
flutter packages pub run build_runner build #利用build_runner设置环境依赖
flutter packages pub run build_runner watch #当创建模型文件时自动创建 “.g.dart”文件
注意:watch 命令不取消会一直运行,只要创建就会生成一个.g.dart 文件 ,
ctrl + C
终端取消。 也可以每次都build 重新生成 。 需要重新生成的可以删除.g.dart文件,重新build 命令。
2.3 创建模型文件
Person.dart
文件
/**Person model class */
import 'package:json_annotation/json_annotation.dart';
part 'Person.g.dart';
///标志class需要实现json序列化功能
@JsonSerializable()
///里面有两个属性 name和id
class Person extends Object {
String name;
int id;
///通过JsonKey重新定义参数名
@JsonKey(name: "details_id")
int detailsId;
/// 构造函数
Person(this.name, this.id, this.detailsId);
/// _$HomeModelFromJson 这个函数在.g.dart中,命名就是类名+FromJson
/// 直接写就行 报错也没关系 生成.g.dart文件之后就好了
factory Person.fromJson(Map json) => _$PersonFromJson(json);
}
五.错误处理
1.出现错误信息: Program ended with exit code: 0
解决方法 :
sudo lsof -i -P | grep -i "listen" # 查看所有监听信息 ,找到占用端口的 【pid】 ,会卡一会查询中 ,进程名字是PerfectTe
kill 【pid】 # pid 是上命令中查到的进程id
WARNING: CocoaPods requires your terminal to be using UTF-8 encoding.