小知识,大挑战!本文正在参与“程序员必备小知识”创作活动。
在Flutter开发中,Dart执行任务原则如同Android中的Handler一样,也是依靠事件驱动的。如图所示,当main方法执行后就生成了一个event loop时间循环,通过event loop不停的从时间队列中获取事件消息来完成程序中所有任务的执行。事件消息包括微任务队列microtask和事件队列event queue,其中microtask的优先级高于event queue,也就是说event loop每执行完毕一次事件后,都会再次查询事件队列中是否存在microtask任务,如果存在则优先执行,直到队列中不再存在microtask任务才会执行event queue任务,所以可以根据此特性在程序中对一个优先级高的任务做事件插队。
下面用代码验证一下。上篇文章介绍了isolate中使用receivePort进行消息通信,这里receivePort的listen监听回调中的代码属于event queue任务,通过Future.microtask方法可以创建一个微任务队列。如控制台所示,当event loop中存在microtask时,它一定会优先执行,而并不是像代码所写的顺序那样按序执行。
void main(){
ReceivePort receivePort = ReceivePort();
receivePort.listen((message) {
print(message);
});
Future.microtask((){
print("这是微任务队列");
});
receivePort.sendPort.send("这是给event queue队列的消息");
Future.microtask((){
print("这是微任务队列2");
});
receivePort.sendPort.send("这是给event queue队列的消息2");
}
在上面的基础上,如果在某个微任务增加耗时操作,则后面的任务都会等待微任务结束后再执行,在如下代码中,在第一个微任务中sleep两秒后,后面的任务才得以执行。所以在使用时,即使要使用microtask插入一个优先级高的任务,也需要注意不要执行耗时较高的操作,这也正是单线程模型的特性。
总结
Dart事件队列循环包括两种队列:
- 事件队列(event queue),包含所有的外来事件:I/O、mouse events、drawing events、timers、isolate之间的信息传递。
- 微任务队列(microtask queue),表示一个短时间内就会完成的异步任务。它的优先级最高,高于event queue,只要队列中还有任务,就可以一直霸占着事件循环。microtask queue添加的任务主要是由 Dart内部产生。
事件循环原则
- 优先执行任务队列中的微任务。
- 即使当前队列中event queue任务数量再多,执行完一个任务后也会再次判断队列里是否包含微任务队列,如果有则执行,若没有则查询是否有event queue任务。