内容简介:接触过Flutter的人都知道,Flutter是用Dart来写的,Dart没有进程和线程的概念,所有的Dart代码都是在isolate上运行的,那么isolate到底是什么?本系列的文章将详细讨论。这篇文章讨论事件队列(event loop)及Dart代码运行顺序。我们对Dart代码进行分类:同步代码和异步代码; 我们在写Dart代码的时候,就只有两种代码,这两类代码是不同的:
接触过Flutter的人都知道,Flutter是用Dart来写的,Dart没有进程和线程的概念,所有的Dart代码都是在isolate上运行的,那么isolate到底是什么?本系列的文章将详细讨论。这篇文章讨论事件队列(event loop)及Dart代码运行顺序。
0x00 同步代码和异步代码
我们对Dart代码进行分类:同步代码和异步代码; 我们在写Dart代码的时候,就只有两种代码,
- 同步代码:就是一行行写下来的代码
- 异步代码:就是以Future等修饰的代码
这两类代码是不同的:
1.运行顺序不同
同步代码和异步代码运行的顺序是不同的:
先运行同步代码,在运行异步代码 复制代码
就是,即使我异步代码写在最前面,同步代码写在最后面,不好意思,我也是先运行后面的同步代码,同步代码都运行完后,在运行前面的异步代码。
2.运行的机制不同
异步代码是运行在 event loop
里的,这是一个很重要的概念,这里可以理解成Android里的Looper机制,是一个死循环, event loop
不断的从事件队列里取事件然后运行。
0x01 event loop 架构
下面是event loop大致的运行图:
这个很好理解,事件events加到Event queue里,Event loop循环从Event queue里取Event执行。
这个理解后,在看event loop详细的运行图:
从这里看到,启动app(start app)后:
- 先查看MicroTask queue是不是空的,不是的话,先运行microtask
- Microtask queue空了之后,在判断Event queue是不是空的,不是的话,运行event
- Event queue空了之后,在继续第1步
这里多了两个名词: MicroTask
和 Event
,这代表了两个不同的异步task
1. MicroTask
这个大家应该不太清楚,但是这个也是 dart:async
提供的异步方法,使用方式:
// Adds a task to the 先查看MicroTask queue. scheduleMicrotask((){ // ...code goes here... }); 复制代码
2.Event
Event我们就很清楚了,就是Future修饰的异步方法,使用方式:
// Adds a task to the Event queue. new Future(() { // ...code goes here... }); 复制代码
0x02
纯粹讲理论知识不太好理解,我们直接上代码,讲一个例子,看如下的代码,请问打印顺序是什么样的?
import 'dart:async'; void main() { print('main #1 of 2'); scheduleMicrotask(() => print('microtask #1 of 3')); new Future.delayed(new Duration(seconds:1), () => print('future #1 (delayed)')); new Future(() => print('future #2 of 4')) .then((_) => print('future #2a')) .then((_) { print('future #2b'); scheduleMicrotask(() => print('microtask #0 (from future #2b)')); }) .then((_) => print('future #2c')); scheduleMicrotask(() => print('microtask #2 of 3')); new Future(() => print('future #3 of 4')) .then((_) => new Future( () => print('future #3a (a new future)'))) .then((_) => print('future #3b')); new Future(() => print('future #4 of 4')); scheduleMicrotask(() => print('microtask #3 of 3')); print('main #2 of 2'); } 复制代码
-
首先运行同步代码
所以是:
main #1 of 2 main #2 of 2 复制代码
-
接下来是异步代码
Dart的异步队列不是我们平常想的那样,一边往队列里加task,一边运行,而是先往队列里添加task,所有task添加完毕,才会运行,所以
Future
的task就添加到event queue
,而scheduleMicrotask
添加到microtask queue
。 -
microtask queue
这里就是:
microtask #1 of 3 microtask #2 of 3 复制代码
-
event queue event queue还有有特殊的情况需要考虑:
-
Future.delayed
需要延迟执行的,Dart是怎么执行的呢,是在延迟时间到了之后才将此task加到
event queue
的队尾,所以万一前面有很耗时的任务,那么你的延迟task不一定能准时运行 -
Future.then
Future.then里的task是不会加入到
event queue
里的,而是当前面的Future执行完后立即掉起,所以你如果想保证异步task的执行顺序一定要用then,否则Dart不保证task的执行顺序这里就是:
future #2 of 4 future #2a future #2b future #2c future #3 of 4 future #4 of 4 microtask #0 (from future #2b) future #3a (a new future) future #3b future #1 (delayed) 复制代码
-
这里你肯定好奇为啥 future #4 of 4
在 future #3 of 4
后面,因为 future #3 of 4
的then里又新建了一个Future,所以这个task会加到 event queue
的最后面。
最后的结果就是:
main #1 of 2 main #2 of 2 microtask #1 of 3 microtask #2 of 3 microtask #3 of 3 future #2 of 4 future #2a future #2b future #2c future #3 of 4 future #4 of 4 microtask #0 (from future #2b) future #3a (a new future) future #3b future #1 (delayed) 复制代码
以上就是本文的全部内容,希望本文的内容对大家的学习或者工作能带来一定的帮助,也希望大家多多支持 码农网
猜你喜欢:- 顺序、条件、循环语句的底层解释
- Spring中循环依赖的正确性与Bean注入的顺序关系
- ViewGroup 默认顺序绘制子 View,如何修改?什么场景需要修改绘制顺序?
- JavaScript万物产生顺序
- SpringBoot配置加载顺序
- SQL语句执行顺序详解
本站部分资源来源于网络,本站转载出于传递更多信息之目的,版权归原作者或者来源机构所有,如转载稿涉及版权问题,请联系我们。
Mastering Regular Expressions, Second Edition
Jeffrey E F Friedl / O'Reilly Media / 2002-07-15 / USD 39.95
Regular expressions are an extremely powerful tool for manipulating text and data. They have spread like wildfire in recent years, now offered as standard features in Perl, Java, VB.NET and C# (and an......一起来看看 《Mastering Regular Expressions, Second Edition》 这本书的介绍吧!