一文彻底搞懂Dart的event队列

概念介绍

event队列和microtask是dart包里的代码,这部分知识是做Flutter必懂的知识,至于event队列和microtask是什么自己谷歌,我就不赘述了。然后我发一段代码,在不运行的情况下,请思考输出什么

第一次练习

void main() {
  methodA();
  methodB();
  methodC('main');
  methodD();
}

methodA(){
  print('A');
}

methodB() async {
  print('B start');
  await methodC('B');
  print('B end');
}

methodC(String from) async {
  print('C start from $from');

  Future((){
    print('C running Future from $from');
  }).then((_){
    print('C end of Future from $from');
  });

  print('C end from $from');
}

methodD(){
  print('D');
}
复制代码

我们可以分析一下,main是同步方法,所以在main方法里调用的方法如果是async的,会执行到await然后返回future,先看methodA();这个不用多说直接输出A。然后看methodB();,因为main是同步方法所以在await之前的直接运行,所以输出B start,然后运行到await methodC('B');,会把methodB加入到event事件队列,然后进入methodC方法直到运行到await方法之前,所以输出C start from BC end from BFuture方法里的内容不输出是因为在这里只是把这个Future加入到event事件队列,然后运行到methodC('main'),同刚才一样,输出C start from mainC end from main,这里的Future方法也是加到了event事件队列,然后执行methodD()方法,输出D,然后同步方法main执行完毕,开始执行event事件队列里的事件,按照刚才加入event事件队列的顺序,先执行methodB(),打印B end,然后打印C running Future from BC end of Future from BC running Future from mainC end of Future from main

添加注释后的代码如下

void main() {
  methodA();
  methodB();
  methodC('main');
  methodD();
}

methodA(){
  print('A');//1
}

methodB() async {
  print('B start');//2
  await methodC('B');//2之后加入到了event队列
  print('B end');//8
}

methodC(String from) async {
  print('C start from $from');//3、5

  Future((){//3之后加到了event队列,from=B、5之后加到了event队列,from=main
    print('C running Future from $from');
  }).then((_){
    print('C end of Future from $from');
  });

  print('C end from $from');//4、6
}

methodD(){
  print('D');//7
}
复制代码

打印结果如下所示:

A
B start
C start from B
C end from B
C start from main
C end from main
D
B end
C running Future from B
C end of Future from B
C running Future from main
C end of Future from main
复制代码

第二次练习

然后我们换一种方式,代码如下

void main() async {
  methodA();
  await methodB();
  await methodC('main');
  methodD();
}

methodA(){
  print('A');
}

methodB() async {
  print('B start');
  await methodC('B');
  print('B end');
}

methodC(String from) async {
  print('C start from $from');

  Future((){
    print('C running Future from $from');
  }).then((_){
    print('C end of Future from $from');
  });

  print('C end from $from');
}

methodD(){
  print('D');
}
复制代码

开始我们的分析,这次的main方法改成了async的,首先输出A,然后执行到await methodB(),进入methodB()方法,输出B start,然后执行await methodC('B'),然后输出C start from B,然后Future加入事件队列,然后输出C end from B,然后这次和上次开始有区别了,因为这次的main方法是async的方法,所以在await methodB()这里会等待methodB()方法执行完毕,所以下一步输出B end,然后执行methodC('main'),输出C start from main,然后Future加入事件队列,然后输出C end from main,然后执行methodD()输出D,然后开始从event队列取事件,按照刚才加入event队列的顺序,一次输出C running Future from BC end of Future from BC running Future from mainC end of Future from main

添加注释后的代码如下

void main() async {
  methodA();
  await methodB();
  await methodC('main');
  methodD();
}

methodA(){
  print('A');//1
}

methodB() async {
  print('B start');//2
  await methodC('B');//因为main方法是async的,所以这里没有加入到event队列而是继续执行
  print('B end');//5
}

methodC(String from) async {
  print('C start from $from');//3 6

  Future((){//3之后加入到event队列、6之后加入到event队列
    print('C running Future from $from');
  }).then((_){
    print('C end of Future from $from');
  });

  print('C end from $from');//4 7
}

methodD(){
  print('D');//8
}
复制代码

打印结果如下所示

A
B start
C start from B
C end from B
B end
C start from main
C end from main
D
C running Future from B
C end of Future from B
C running Future from main
C end of Future from main
复制代码

总结

如果async的方法被同步方法调用,代码会执行到第一个await之前,然后把当前future加入到event队列;如果async的方法被async的方法调用,那么在执行到await的时候会等待执行完毕。

还有一个microtask,原理和这个一样,混合使用的时候,在主方法执行完毕以后,会先取microtask队列的事件执行,都执行完以后再从event队列里取事件执行。

有问题请留言,欢迎加入QQ群:457664582,如果你是一个喜欢思考的人,欢迎加入群一起交流学习,拒绝伸手党。

转载于:https://juejin.im/post/5d031adb6fb9a07efd47092d

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值