阅读 329

Flutter(二十四)-Dart事件循环机制

我们在前面已经大致了解了FlutterFuture的运行机制,那么除了FutureFlutter中是否还有其他任务机制呢?

我们先来看一段代码:

void testFuture() {   print('外部代码1');   Future(() => print('任务A')).then((value) => print('A任务结束'));   Future(() => print('任务B')).then((value) => print('B任务结束'));   print('外部代码2'); } 复制代码

按照我们在之前文章中介绍的Future的用法及执行流程,我们很容易就能猜到运行结果:

image.png

那么,如果在代码运行过程中,突然有紧急任务需要先执行,那么有没有办法处理呢?这就要使用到微任务来做处理了;

scheduleMicrotask

scheduleMicrotask又称为微任务,我们将代码修改一下,添加一个微任务看一下代码的执行流程发生了什么变化?我们将代码修改如下:

void testFuture() {   print('外部代码1');   Future(() => print('任务A')).then((value) => print('A任务结束'));   Future(() => print('任务B')).then((value) => print('B任务结束'));   scheduleMicrotask(() {     print('微任务A');   });   sleep(const Duration(seconds: 1));   print('外部代码2'); } 复制代码

在代码的执行流程中添加了scheduleMicrotask微任务,那么代码的执行结果是什么呢?

iShot2021-11-14 17.40.49.gif

根据打印信息,我们发现我们在Future后边添加的scheduleMicrotask微任务竟然优先执行了;scheduleMicrotask拥有较高的优先级,进而我们也能够确定在这段代码执行的过程中是有两个队列存在的,否则微任务不发优先执行;

Dart中的队列

Dart中是有两种对类存在的:

  • event queue事件队列:这种队列包含所有的外来事件,如I/Omouse eventsdrawing eventstimersIsolate等之间的信息传递;

  • microtask queue微任务队列:这种队列表示一个短时间内就会完成的异步任务。它的优先级最高,只要此队列中还有任务,就可以一直霸占着事件循环。microtask queue添加的任务主要是由Dart内部产生的。

需要注意的是,正因为microtask queue队列的优先级高于event queue队列,所以如果在microtask queue中的微任务过多,那么就有可能一直霸占当前的事件循环(event loop)。从而对event queue中的触摸、绘制等事件产生影响,导致这些时间产生阻塞卡顿;

在每一次的事件循环中,Dart总是会优先在microtask queue队列中查询是否还有可执行的任务,如果该队列中没有需要处理的任务,那么才会处理event queue队列中的任务及其流程;

在异步任务中,我们使用的最多的还是优先级较低的event queueDart中为event queue的任务做了一层封装,也就是我们之前使用过的Future

DartFuture异步任务的执行流程:

  • 声明一个Future时,Dart会将异步任务的函数执行体放入event queue中,然后立即返回,后续的代码继续进行同步执行;

  • 当同步执行的代码执行完毕后,event queue会按照加入的顺序也就是声明顺序,依次取出事件,最后同步执行Future的函数体及后续操作;

事件示例

我们来定义一串任务,代码如下:

void testFuture() {   Future f1 = Future(() => null);   f1.then((value) {    print('6');   }).then((value) => print('7'));   Future f2 = Future(() => print('1'));   f2.then((value){     print('4');   });   Future(() => print('2'));   scheduleMicrotask(() {     print('3');   });   print('5'); } 复制代码

按照我们对Future任务执行顺序的理解,以及scheduleMicrotask具有较高优先级的执行权,那么其打印顺序应该是:

5、3、6、7、1、4、2

我们查看打印结果:

image.png

确实和我们预料的一样,那么我们将代码作如下修改呢?

void testFuture() {   Future f1 = Future(() => null);   f1.then((value) {    print('6');    scheduleMicrotask(() {      print('8');    });   }).then((value) => print('7'));   Future f2 = Future(() => print('1'));   f2.then((value){     print('4');   });   Future(() => print('2'));   scheduleMicrotask(() {     print('3');   });   print('5'); } 复制代码

我们在f1的任务中,添加了一个微任务,那么我们来看一下此时的打印结果:

image.png

看到这个结果,我们不免会产生疑问?scheduleMicrotask是微任务,那么他的优先级应该是最高的,那么8为什么会在7的后边打印呢?

此处需要注意的是,then内部的代码,我们可以看做这部分代码被扔在了微任务队列中,而scheduleMicrotask虽然也是微任务,但是此时它仅仅是扔在了微任务队列中,当前的微任务队列中还有打印7的任务,所以最终是78的前边打印;


作者:枸杞菊花保温杯
链接:https://juejin.cn/post/7033204529105469447


文章分类
代码人生
版权声明:本站是系统测试站点,无实际运营。本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌抄袭侵权/违法违规的内容, 请发送邮件至 XXXXXXo@163.com 举报,一经查实,本站将立刻删除。
相关推荐