接触过Flutter的人都知道,Flutter是用Dart来写的,Dart没有进程和线程的概念,全部的Dart代码都是在isolate上运行的,那么isolate究竟是什么?本系列的文章将详细讨论。这篇文章讨论事件队列(event loop)及Dart代码运行顺序。web
咱们对Dart代码进行分类:同步代码和异步代码; 咱们在写Dart代码的时候,就只有两种代码,bash
这两类代码是不一样的:架构
同步代码和异步代码运行的顺序是不一样的:app
先运行同步代码,在运行异步代码
复制代码
就是,即便我异步代码写在最前面,同步代码写在最后面,很差意思,我也是先运行后面的同步代码,同步代码都运行完后,在运行前面的异步代码。异步
异步代码是运行在event loop
里的,这是一个很重要的概念,这里能够理解成Android里的Looper机制,是一个死循环,event loop
不断的从事件队列里取事件而后运行。async
下面是event loop大体的运行图: oop
这个理解后,在看event loop详细的运行图: ui
从这里看到,启动app(start app)后:spa
这里多了两个名词:MicroTask
和Event
,这表明了两个不一样的异步task线程
并且能够看出:
MicroTask
这个你们应该不太清楚,可是这个也是dart:async
提供的异步方法,使用方式:
// Adds a task to the 先查看MicroTask queue.
scheduleMicrotask((){
// ...code goes here...
});
复制代码
或者:
new Future.microtask((){
// ...code goes here...
});
复制代码
Event咱们就很清楚了,就是Future修饰的异步方法,使用方式:
// Adds a task to the Event queue.
new Future(() {
// ...code goes here...
});
复制代码
纯粹讲理论知识不太好理解,咱们直接上代码,讲一个例子,看以下的代码,请问打印顺序是什么样的?
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'))
.then((_){
new Future(() => print('future #4a'));
})
.then((_) => print('future #4b'));
scheduleMicrotask(() => print('microtask #3 of 3'));
print('main #2 of 2');
}
复制代码
首先运行同步代码
因此是:
main #1 of 2
main #2 of 2
复制代码
接下来是异步代码
Dart的Event Loop是先判断 microtask queue
里有没有task,有的话运行microtask
,microtask
运行完后,在运行event queue
里的event task
,一个event task
运行完后,再去运行 microtask queue
,而后在运行event 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的执行顺序
scheduleMicrotask
一个event task
运行完后,会先去查看Micro queue
里有没有能够执行的micro task
。没有的话,在执行下一个event task
这里就是:
```
future #2 of 4
future #2a
future #2b
future #2c
microtask #0 (from future #2b)
future #3 of 4
future #4 of 4
future #4b
future #3a (a new future)
future #3b
future #4a
future #1 (delayed)
```
复制代码
这里你确定好奇为啥future #3 of 4
后面是future #4 of 4
,而不是future #3a (a new future)
,由于 future #3 of 4
的then里又新建了一个Future:future #3a (a new future)
,因此future #3a (a new 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
microtask #0 (from future #2b)
future #3 of 4
future #4 of 4
future #4b
future #3a (a new future)
future #3b
future #4a
future #1 (delayed)
复制代码