Flutter学习指南(4):Dart语言(2)---开源网络库dio

dio 是dart 开源的网络库 ,基于dart语言 。使用简单,性能稳定 。

一.dio的架构

执行流:

请求拦截器 >> 请求转换器 >> 发起请求 >> 响应转换器 >> 响应拦截器 >> 最终结果。

支持的功能:

http、FormData、拦截器、请求取消、Cookie管理、文件上传/下载、超时、错误处理、转换器、代理。

二、 开始实验

1. 引入包

知识点:
1.flutter有自己的包管理仓库 Pub

  1. flutter可以引入 pub包,本地路径包,git包 ,github包
  2. flutter核心库不包含颜色,要使用 css_colors 第三方库
  3. 要使用浏览器 要参考 url_launcher第三方库

使用方法:

1.打开 pubspec.yaml 文件,然后在dependencies下添加dio: 2.1.x (表示最新版)


  1. 终端运行
flutter packages get
终端显示完成

3.在main.dart中引入开始使用


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/flutter-in-action@1.0/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<int>
      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<int> 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 禁止运行时反射

  1. 单个无依赖的model 可以使用 JSON.decode()
class User {
  final String name;
  final String email;

  User(this.name, this.email);

  User.fromJson(Map<String, dynamic> json)
      : name = json['name'],
        email = json['email'];

  Map<String, dynamic> 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_serializablebuilt_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<String, dynamic> 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.

©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 214,504评论 6 496
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 91,434评论 3 389
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 160,089评论 0 349
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 57,378评论 1 288
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 66,472评论 6 386
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 50,506评论 1 292
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 39,519评论 3 413
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 38,292评论 0 270
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 44,738评论 1 307
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 37,022评论 2 329
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 39,194评论 1 342
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 34,873评论 5 338
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 40,536评论 3 322
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 31,162评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,413评论 1 268
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 47,075评论 2 365
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 44,080评论 2 352

推荐阅读更多精彩内容