消息队列与循环
消息队列与循环

Dart 为单线程(此处不讲 isolate),内涵两个任务任务队列,一个消息循环。

  • Event Queue
  • MicroTask Queue

event 队列:包含所有外来的事件:I/O,mouse events,drawing events,timers,isolate之间的message等。

microtask 队列:包含来自当前isolate的内部代码。


执行过程
执行过程

由上图可见:启动app后先执行 main 方法,结束后检查 microtask 队列,如果不为空,则执行其中的任务。当 microtask 内无任务时,再检查 event 队列,执行其中任务,完成后退出app。

注意:当事件循环正在处理micro task的时候。event队列会被堵塞。这时候app就无法进行UI绘制,响应鼠标事件和I/O等事件

任务执行顺序是无法精准预测的,因为单线程的原因,所以当你执行一个延迟 1s 任务时,必须等待队列前的任务全部执行完成后才会执行此延迟任务,此时可能已经过了 1s。

// 一秒以后将任务添加至event队列
new Future.delayed(const Duration(seconds:1), () {
  //任务具体代码
});

虽然上面这个例子中一秒后向event队列添加一个任务,但是这个任务想要被执行的话必须满足一下几点:

  1. main 方法执行完毕
  2. microtask 队列为空
  3. 该任务前的任务全部执行完毕所以该任务真正被执行可能是大于 1 秒后。

Future 链式调用

如果在异步任务中存在前后代码依赖,那么应该使用 then 链式调用。

// 明确表现出了后者依赖前者设置的变量值
future.then(...set an important variable...)
  .then((_) {...use the important variable...});

而非(错误写法):

// 这样写错误的原因就是没有明确体现出设置变量和使用变量之间的依赖关系
future.then(...set an important variable...);
Timer.run(() {...use the important variable...});

安排任务

Future 向 event 队列尾部添加一个事件

Future((){});

scheduleMicrotask 向 microtask 队列尾部添加一个事件。

scheduleMicrotask((){});

关于Future的有趣事实

  1. 被添加到 then() 中的方法会在Future执行后立马执行(这方法没有被加入任何队列,只是被回调了)。
  2. 如果在 then() 调用之前Future就已经执行完毕了,那么会有一个任务被加入到microtask 队列中。这个任务执行的就是被传入 then 的方法。
  3. Future() 和 Future.delayed() 构造方法并不会被立刻完成,他们会向event队列中添加一个任务。
  4. Future.value()构造方法会在一个 microtask 中完成。
  5. Future,sync()构造方法会立马执行其参数方法,并在 microtask 中完成。

参考:

https://www.dartlang.org/articles/event-loop/

https://www.jianshu.com/p/7549b63a72d7

https://blog.csdn.net/qizewei123/article/details/89190415


Android 开发者、影视后期内容(包装)制作者、Unity 2D游戏开发者