Dart是一个单线程语言,可以理解成物理线路中的串联,当其遇到有延迟的运算(比如IO操作、延时执行)时,线程中按顺序执行的运算就会阻塞,用户就会感觉到卡顿,于是通常用异步处理来解决这个问题。

Dart异步编程有两种方式:Future和Stream

Future相当于40米大砍刀,Stream相当于一捆40米大砍刀。dart提供了关键字async(异步)和await(延迟执行),相当于普通的便捷的小匕首,而小匕首是我们平时经常用到的。

当遇到有需要延迟的运算(async)时,将其放入到延迟运算的队列(await)中去,把不需要延迟运算的部分先执行掉,最后再来处理延迟运算的部分。

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关键字

就是说:

1.要想 return await … ,那么方法首先是 async 的,如上方方法。

2.使用 async 标注的方法,必须要用 await 接收返回值,比如上方方法在接收返回值时,需要加入 await

var data = await getData();

什么是Future

Future表示一件“将来”会发生的事情,将来可以从Future中取到一个值。当一个方法返回一个Future的事情,发生两件事情:

  • 这个方法将某件事情排队,返回一个未完成的Future
  • 当这件事情完毕之后,Future的状态会变成已完成,这个时候就可以取到这件事情的返回值了。

要取到这个“返回值”,有两种方式:

  • 使用async配合await
  • 使用Future提供的api

我们看这两种实现方式的案例:

1、使用async配合await

先看个案例,等待3秒后返回‘我是用户’:

/*模拟异步加载用户信息*/
Future _getUserInfo() async{
await new Future.delayed(new Duration(milliseconds: ));
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 ( ): initState:-- ::40.097339
I/flutter ( ): _loadUserInfo:-- ::40.103542
I/flutter ( ): Instance of 'Future<dynamic>'
I/flutter ( ): initState:-- ::40.108510
I/flutter ( ): 我是用户
I/flutter ( ): _loadUserInfo:-- ::43.117136

what?

很明显,打印结果并没有按照串联的方式依次打印。

flutter中会改造带asyc关键字的方法,让这个方法脱离主流程,变成“后面一点”执行(通过scheduleMicrotask),所以可以让我们的程序“看起来”是顺序执行的。

2、Future api

我们修改一下 loadUserInfo() 方法:

/*加载用户信息,顺便打印时间看看顺序*/
Future _loadUserInfo() async{
print("_loadUserInfo:${new DateTime.now()}");
_getUserInfo().then((info){
print(info);
});
print("_loadUserInfo:${new DateTime.now()}");
}

再次运行输出一下:

I/flutter ( ): initState:-- ::32.488765
I/flutter ( ): _loadUserInfo:-- ::32.494751
I/flutter ( ): _loadUserInfo:-- ::32.499725
I/flutter ( ): Instance of 'Future<dynamic>'
I/flutter ( ): initState:-- ::32.499970
I/flutter ( ): 我是用户

两次输出是有不同的,主要不同在于第二个 loadUserInfo 的日志打印,与‘我是用户’的输出顺序,为什么有差异?

await会阻塞流程,等待紧跟着的的Future执行完毕之后,再执行下一条语句,而如果用了Future.then这个api,那么就不会等待,直接执行下面的语句,等Future执行完了,再调用then这个方法。

总结

在请求方法中直接 return await .. .的时候,实际上返回的是一个延迟计算的Future对象。

有两点需要注意:

  • await关键字必须在async函数内部使用
  • 调用async函数必须使用await关键字

Flutter 中有两种实现异步编程的方式:Future api、 async await

日常开发中常用的是 async await Future 搭配。

Flutter 的异步机制Future的更多相关文章

  1. flutter中的异步机制Future

    饿补一下Flutter中Http请求的异步操作. Dart是一个单线程语言,可以理解成物理线路中的串联,当其遇到有延迟的运算(比如IO操作.延时执行)时,线程中按顺序执行的运算就会阻塞,用户就会感觉到 ...

  2. flutter中的异步机制 Future

    饿补一下Flutter中Http请求的异步操作. Dart是一个单线程语言,可以理解成物理线路中的串联,当其遇到有延迟的运算(比如IO操作.延时执行)时,线程中按顺序执行的运算就会阻塞,用户就会感觉到 ...

  3. 深入理解Spring的异步机制

    一.Spring中实现异步执行 在这里我先以事件的机制举例,注意默认情况下事件的发布与监听都是同步执行的.那么我们来看一看基于异步事件的例子该怎么写 首先还是定义事件: package com.bdq ...

  4. Netty 中的异步编程 Future 和 Promise

    Netty 中大量 I/O 操作都是异步执行,本篇博文来聊聊 Netty 中的异步编程. Java Future 提供的异步模型 JDK 5 引入了 Future 模式.Future 接口是 Java ...

  5. 结合源码看nginx-1.4.0之nginx异步机制详解

    目录 0. 摘要 1. nginx异步设计思想 2. nginx异步设计数据结构 3. nginx异步机制源码解析 4. 一个简单的应用异步例子 5. 小结 6. 参考源码

  6. JavaScript的异步机制

    我们经常说JS是单线程的,比如node.js研讨会上大家都说JS的特色之一是单线程的,这样使JS更简单明了,可是大家真的理解所谓JS的单线程机制吗?单线程时,基于事件的异步机制又该当如何 1 先看下两 ...

  7. JavaScript单线程和异步机制

    随着对JavaScript学习的深入和实践经验的积累,一些原理和底层的东西也开始逐渐了解.早先也看过一些关于js单线程和事件循环的文章,不过当时看的似懂非懂,只留了一个大概的印象:浏览器中的js程序时 ...

  8. [转]JavaScript异步机制详解

    原文: https://www.jianshu.com/p/4ea4ee713ead --------------------------------------------------------- ...

  9. Windows store app[Part 4]:深入WinRT的异步机制

    接上篇Windows store app[Part 3]:认识WinRT的异步机制 WinRT异步机制回顾: IAsyncInfo接口:WinRT下异步功能的核心,该接口提供所有异步操作的基本功能,如 ...

随机推荐

  1. 手把手教你在CentOS上搭建Kubernetes集群

    作者:ChamPly 安装CentOS 1.安装net-tools [root@localhost ~]# yum install -y net-tools 2.关闭firewalld [root@l ...

  2. Java并发包--ArrayBlockingQueue

    转载请注明出处:http://www.cnblogs.com/skywang12345/p/3498652.html ArrayBlockingQueue介绍 ArrayBlockingQueue是数 ...

  3. Java集合--ArrayList出现同步问题的原因

    1 fail-fast简介 fail-fast 机制是java集合(Collection)中的一种错误机制.当多个线程对同一个集合的内容进行操作时,就可能会产生fail-fast事件.例如:当某一个线 ...

  4. PyPI教程

    Wiki PyPI The Python Package Index, abbreviated as PyPI and also known as the Cheese Shop (a referen ...

  5. SP703 SERVICE - Mobile Service

    思路:DP 提交:1次 题解: 我们把处理到的要求作为阶段. \(f[i][x][y][z]\)表示第 \(i\) 个要求,三个人分别的位置. 发现这样有很多无用状态,因为显然在第 \(i\) 个要求 ...

  6. 001_89C52之_Proteus_ADC0809采集电压

    一)使用ADC0809采集直流电压 1. 第一个数码管显示的是采样输入口 2. 后面三位是采样电压 (二)使用ADC0809进行交流电的采样 1. 先进行交流电降压,即用变压器降压后使用整桥电路进行整 ...

  7. iOS Jenkins 自动化打包构建

    前言 在测试app项目过程中,通常都是需要开发打测试包给到测试,但是无论是iOS还是Android的打包过程都是相当漫长的,频繁的回归测试需要频繁的打包,对于开发同学影响还是蛮大的.因此在这种情况下, ...

  8. jvm 线程状态

    NEW: Just starting up, i.e., in process of being initialized.NEW_TRANS: Corresponding transition sta ...

  9. Linux设备驱动程序 之 vmalloc

    vmalloc()函数的工作方式类似于kmalloc(),只不过在前者分配的内存虚拟地址是连续的,而物理地址则无须连续:这也是用户空间分配函数的工作方式:由malloc()返回的页在进程的虚拟地址空间 ...

  10. centos7 安装 mysql(在线安装)

    在CentOS中默认安装有MariaDB,这个是MySQL的分支,但为了需要,还是要在系统中安装MySQL,而且安装完成之后可以直接覆盖掉MariaDB. 1 下载并安装MySQL官方的 Yum Re ...