flutter中的异步机制 Future
饿补一下Flutter中Http请求的异步操作。
Dart是一个单线程语言,可以理解成物理线路中的串联,当其遇到有延迟的运算(比如IO操作、延时执行)时,线程中按顺序执行的运算就会阻塞,用户就会感觉到卡顿,于是通常用异步处理来解决这个问题。
Dart异步编程有两种方式:Future和Stream
Future相当于40米大砍刀,Stream相当于一捆40米大砍刀。dart提供了关键字async(异步)和await(延迟执行),相当于普通的便捷的小匕首,而小匕首是我们平时经常用到的。
当遇到有需要延迟的运算(async)时,将其放入到延迟运算的队列(await)中去,把不需要延迟运算的部分先执行掉,最后再来处理延迟运算的部分。
1、async和await
async await 这两个关键字是dart语言的特性,能让你写出看起来像是“同步”的“异步”代码,先看一个方法案例:
/*HTTP的get请求返回值为Future<String>类型,即其返回值未来是一个String类型的值*/
/*async关键字声明该函数内部有代码需要延迟执行*/
getData() async {
/*await关键字声明运算为延迟执行,然后return运算结果*/
return await http.get(Uri.encodeFull(url), headers: {"Accept": "application/json"});
}
然后我们尝试调用这个方法,并获取返回值。
String data = getDate();
然后控制台报错了….
为什么呢?因为data是String类型,而函数getData()是一个异步操作函数,其返回值是一个await延迟执行的结果。在Dart中,有await标记的运算,其结果值都是一个Future对象,Future不是String类型,所以就报错了。
总结一下:
在请求方法中直接 return await .. .的时候,实际上返回的是一个延迟计算的Future对象。
还有两点需要注意:
- await关键字必须在async函数内部使用
- 调用async函数必须使用await关键字
后面两点怎么讲?
- 要想 return await … ,那么方法首先是 async 的,如上方方法。
- 使用 async 标注的方法,必须要用 await 接收返回值,比如上方方法在接收返回值时,需要加入 await ,var data = await getData();
2、什么是Future
Future表示一件“将来”会发生的事情,将来可以从Future中取到一个值。当一个方法返回一个Future的事情,发生两件事情:
- 这个方法将某件事情排队,返回一个未完成的Future
- 当这件事情完毕之后,Future的状态会变成已完成,这个时候就可以取到这件事情的返回值了。
要取到这个“返回值”,有两种方式:
- 使用async配合await
- 使用Future提供的api
我们看这两种实现方式的案例:
2.1、使用async配合await
先看个案例,等待3秒后返回‘我是用户’:
/*模拟异步加载用户信息*/
Future _getUserInfo() async{
await new Future.delayed(new Duration(milliseconds: 3000));
return "我是用户";
} /*加载用户信息,顺便打印时间看看顺序*/
Future _loadUserInfo() async{
print("_loadUserInfo:${new DateTime.now()}");
print(await _getUserInfo());
print("_loadUserInfo:${new DateTime.now()}");
}
我们在initState中调用该方法:
@override
void initState(){
print("initState:${new DateTime.now()}");
_loadUserInfo();
print("initState:${new DateTime.now()}"); super.initState();
}
打印结果如下:
I/flutter ( 1802): initState:2019-06-20 09:46:40.097339
I/flutter ( 1802): _loadUserInfo:2019-06-20 09:46:40.103542
I/flutter ( 1802): Instance of 'Future<dynamic>'
I/flutter ( 1802): initState:2019-06-20 09:46:40.108510
I/flutter ( 1802): 我是用户
I/flutter ( 1802): _loadUserInfo:2019-06-20 09:46:43.117136
what?
很明显,打印结果并没有按照串联的方式依次打印。
flutter中会改造带asyc关键字的方法,让这个方法脱离主流程,变成“后面一点”执行(通过scheduleMicrotask),所以可以让我们的程序“看起来”是顺序执行的。
2.2、Future api
我们修改一下 loadUserInfo() 方法:
/*加载用户信息,顺便打印时间看看顺序*/
Future _loadUserInfo() async{
print("_loadUserInfo:${new DateTime.now()}");
_getUserInfo().then((info){
print(info);
});
print("_loadUserInfo:${new DateTime.now()}");
}
再次运行输出一下:
I/flutter ( 1802): initState:2019-06-20 09:50:32.488765
I/flutter ( 1802): _loadUserInfo:2019-06-20 09:50:32.494751
I/flutter ( 1802): _loadUserInfo:2019-06-20 09:50:32.499725
I/flutter ( 1802): Instance of 'Future<dynamic>'
I/flutter ( 1802): initState:2019-06-20 09:50:32.499970
I/flutter ( 1802): 我是用户
两次输出是有不同的,主要不同在于第二个 loadUserInfo 的日志打印,与‘我是用户’的输出顺序,为什么有差异?
await会阻塞流程,等待紧跟着的的Future执行完毕之后,再执行下一条语句,而如果用了Future.then这个api,那么就不会等待,直接执行下面的语句,等Future执行完了,再调用then这个方法。
3、总结
在请求方法中直接 return await .. .的时候,实际上返回的是一个延迟计算的Future对象。
有两点需要注意:
- await关键字必须在async函数内部使用
- 调用async函数必须使用await关键字
Flutter 中有两种实现异步编程的方式:Future api、 async await
日常开发中常用的是 async await Future 搭配。
flutter中的异步机制 Future的更多相关文章
- flutter中的异步机制Future
饿补一下Flutter中Http请求的异步操作. Dart是一个单线程语言,可以理解成物理线路中的串联,当其遇到有延迟的运算(比如IO操作.延时执行)时,线程中按顺序执行的运算就会阻塞,用户就会感觉到 ...
- Flutter 的异步机制Future
Dart是一个单线程语言,可以理解成物理线路中的串联,当其遇到有延迟的运算(比如IO操作.延时执行)时,线程中按顺序执行的运算就会阻塞,用户就会感觉到卡顿,于是通常用异步处理来解决这个问题. Dart ...
- Netty 中的异步编程 Future 和 Promise
Netty 中大量 I/O 操作都是异步执行,本篇博文来聊聊 Netty 中的异步编程. Java Future 提供的异步模型 JDK 5 引入了 Future 模式.Future 接口是 Java ...
- ajax中的异步机制导致的问题
设置async:false;即可将请求设置为同步的,所以,我们就可以实现:在ajax请求之后再执行下面的语句.
- JS中的异步以及事件轮询机制
一.JS为何是单线程的? JavaScript语言的一大特点就是单线程,也就是说,同一个时间只能做一件事.那么,为什么JavaScript不能有多个线程呢?这样能提高效率啊.(在JAVA和c#中的异步 ...
- 深入理解 JS 引擎执行机制(同步执行、异步执行以及同步中的异步执行)
首先明确两点: 1.JS 执行机制是单线程. 2.JS的Event loop是JS的执行机制,深入了解Event loop,就等于深入了解JS引擎的执行. 单线程执行带来什么问题? 在JS执行中都是单 ...
- Flutter 中使用Future消除Callback Hell
/先分别定义各个异步任务 Future<String> login(String userName, String pwd){ ... //用户登录 }; Future<String ...
- 深入理解Spring的异步机制
一.Spring中实现异步执行 在这里我先以事件的机制举例,注意默认情况下事件的发布与监听都是同步执行的.那么我们来看一看基于异步事件的例子该怎么写 首先还是定义事件: package com.bdq ...
- [译]Python中的异步IO:一个完整的演练
原文:Async IO in Python: A Complete Walkthrough 原文作者: Brad Solomon 原文发布时间:2019年1月16日 翻译:Tacey Wong 翻译时 ...
随机推荐
- Mysql基础学习_Windows版(一)
1.Mysql简介 Mysql是一种关系数据库管理系统,关系数据库将数据保存在不同的表中,而不是将所有数据放在一个大仓库内,这样就增加了速度并提高了灵活性.所谓的关系型数据库,是建立在关系模型基础上的 ...
- 关于Objective C的私有函数
(1)很多从其他语言(例如C++)转到objective c的初学者,往往会问到一个问题,如何定义类的私有函数?这里的“私有函数”指的是,某个函数只能在类的内部使用,不能在类的外部,或者派生类内部使用 ...
- ASE19团队项目beta阶段Backend组 scrum7 记录
本次会议于12月13日,19:30在微软北京西二号楼sky garden召开,持续10分钟. 与会人员:Hao Wang, Lihao Ran, Xin Kang 请假人员:Zhikai Chen 每 ...
- Axure工作区间
Axure的工作环境可进行可视化拖拉操作,可轻松快速的创建带有注释的线框图.无需编程就可以在线框图中定义简单链接和高级交互.Axure可一体化生成线框图.HTML交互原型.规格说明Word文档.以下是 ...
- 使用SQLAlchemy,以及问题处理
https://www.liaoxuefeng.com/wiki/001374738125095c955c1e6d8bb493182103fac9270762a000/0014021031294178 ...
- ELK6.x_Kafka 安装配置文档
1. 环境描述 1.1. 环境拓扑 如上图所示:Kafka为3节点集群负责提供消息队列,ES为3节点集群.日志通过logstash或者filebeat传送至Kafka集群,再通过logstash发 ...
- 熟记这些python内置函数,你离大佬就不远了
python内置了很多函数,方便我们在写程序的时候调用,在ython 2.7 的所有内置函数共有80个.熟练记住和使用这些内置函数,将大大提高写Python代码的速度和代码的优雅程度. 以下代码示例用 ...
- 通过Java调用Python脚本
在进行开发的过程中,偶尔会遇到需要使用Java调用Python脚本的时候,毕竟Python在诸如爬虫,以及科学计算等方面具有天然的优势.最近在工作中遇到需要在Java程序中调用已经写好的Python程 ...
- XSS攻击(跨站攻击)
漏洞描述 跨站脚本攻击(Cross-site scripting,简称XSS攻击),通常发生在客户端,可被用于进行隐私窃取.钓鱼欺骗.密码偷取.恶意代码传播等攻击行为.XSS攻击使用到的技术主要为HT ...
- SpringBoot + MySQL + MyBatis 整合 Redis 实现缓存操作
本地安装 Redis Redis 安装:https://www.cnblogs.com/oukele/p/11373052.html 项目结构: SpringBootRedis 工程项目结构如下: ...