深入了解Flutter的isolate(1) —- 事件循环(event loop)及代码运行顺序

深入了解Flutter的isolate(1) —- 事件循环(event loop)及代码运行顺序

前言

接触过Flutter的人都知道,Flutter是用Dart来写的,Dart没有进程和线程的概念,所有的Dart代码都是在isolate上运行的,那么isolate到底是什么?本系列的文章将详细讨论。这篇文章讨论事件队列(event loop)及Dart代码运行顺序。

0x00 同步代码和异步代码

我们对Dart代码进行分类:同步代码和异步代码; 我们在写Dart代码的时候,就只有两种代码,

  • 同步代码:就是一行行写下来的代码
  • 异步代码:就是以Future等修饰的代码

这两类代码是不同的:

1.运行顺序不同

同步代码和异步代码运行的顺序是不同的:

先运行同步代码,在运行异步代码
复制代码

就是,即使我异步代码写在最前面,同步代码写在最后面,不好意思,我也是先运行后面的同步代码,同步代码都运行完后,在运行前面的异步代码。

2.运行的机制不同

异步代码是运行在event loop里的,这是一个很重要的概念,这里可以理解成Android里的Looper机制,是一个死循环,event loop不断的从事件队列里取事件然后运行。

0x01 event loop 架构

下面是event loop大致的运行图:

这个很好理解,事件events加到Event queue里,Event loop循环从Event queue里取Event执行。

这个理解后,在看event loop详细的运行图:

从这里看到,启动app(start app)后:

  1. 先查看MicroTask queue是不是空的,不是的话,先运行microtask
  2. 一个microtask运行完后,会看有没有下一个microtask,直到Microtask queue空了之后,才会去运行Event queue 3.在Evnet queue取出一个event task运行完后,又会跑到第一步,去运行microtask

这里多了两个名词:MicroTaskEvent,这代表了两个不同的异步task

而且可以看出:

  • 如果想让任务能够尽快执行,就用MicroTask

1. MicroTask

这个大家应该不太清楚,但是这个也是dart:async提供的异步方法,使用方式:

// Adds a task to the 先查看MicroTask queue.
scheduleMicrotask((){
  // ...code goes here...
}); 
复制代码

或者:

new Future.microtask((){
    // ...code goes here...
});
复制代码

2.Event

Event我们就很清楚了,就是Future修饰的异步方法,使用方式:

// Adds a task to the Event queue.
new Future(() {
  // ...code goes here...
});
复制代码

0x02

纯粹讲理论知识不太好理解,我们直接上代码,讲一个例子,看如下的代码,请问打印顺序是什么样的?

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');
}
复制代码
  1. 首先运行同步代码

    所以是:

    main #1 of 2
    main #2 of 2
    复制代码
  2. 接下来是异步代码

    Dart的Event Loop是先判断 microtask queue里有没有task,有的话运行microtaskmicrotask运行完后,在运行event queue里的event task,一个event task 运行完后,再去运行 microtask queue,然后在运行event queue

  3. microtask queue

    这里就是:

    microtask #1 of 3
    microtask #2 of 3
    复制代码
  4. 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 #4 of 4future #3 of 4后面,因为 future #3 of 4的then里又新建了一个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)
复制代码

参考文章

webdev.dartlang.org/articles/pe…

版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 举报,一经查实,本站将立刻删除。

发布者:全栈程序员-用户IM,转载请注明出处:https://javaforall.cn/101216.html原文链接:https://javaforall.cn

【正版授权,激活自己账号】: Jetbrains全家桶Ide使用,1年售后保障,每天仅需1毛

【官方授权 正版激活】: 官方授权 正版激活 支持Jetbrains家族下所有IDE 使用个人JB账号...

(0)


相关推荐

  • 游戏中的“垂直同步”与“三重缓冲”究竟是个啥?[通俗易懂]

    游戏中的“垂直同步”与“三重缓冲”究竟是个啥?[通俗易懂]从今天开始,我们会开启“小教程”的兄弟栏目——小科普,给大家介绍在配电脑或玩游戏过程中经常会遇到的专业名词。第一期“小科普”我们来讲讲游戏中经常会遇到的一个画面选项——垂直同步我们曾在一期语音里和大家讲探讨过垂直同步的功用,可惜语音有60秒的长度限制,并不能和大家解释清楚,那么今天就来详细分析一下“垂直同步”:它到底是干嘛用的?它有什么缺点吗?

  • ANDROID自己定义视图——onLayout源代码 流程 思路具体解释[通俗易懂]

    ANDROID自己定义视图——onLayout源代码 流程 思路具体解释

  • 小米手机-解BL锁+开ROOT权限

    小米手机-解BL锁+开ROOT权限在小米社区和网址https://miuiver.com/上,有MIUI的历史版本,还有刷机教程等等本文是参考上述的教程,并结合自己在刷机过程中,出现的问题进行记录并得到解决方案下面主要是,重要部分,同时还有一些容易出错的地方解BL锁要提前,在设置–更多设置–开发者模式–设备解锁状态中,绑定账号和设备,注意的地方,不要重复绑定设备,不然时间会重新计算的,吃亏了2次。只要登陆过一个小米账号,点击绑定一次即可。如果没有找到开发者模式,就先设置–我的设备–全部参数–.

  • 制作zencart模板的几个步骤

    制作zencart模板的几个步骤很多做外贸站的朋友都在为自己的网店模板而头疼不已,本来踌躇满志的要好好做网站,但是当你用网店程序的时候,发现zencart程序里面默认的模板都不怎么好看。于是乎,四处寻找,找了这个想要那个,结果不是不能用就是功能不全。而且最大的威胁就是不安全,万一有个什么其他的代码嵌在里面,你也发现不了。这对于做外贸的你来说是得不偿失的,那么,你是否想要自己做一个你喜欢的模板呢?是不是苦于没有方法呢?易搜今天就来…

  • Pycharm全局搜索关键字[通俗易懂]

    Pycharm全局搜索关键字[通俗易懂]PythonTips

  • 文件上传的三种方式-Java「建议收藏」

    文件上传的三种方式-Java「建议收藏」前言:因自己负责的项目(jetty内嵌启动的SpringMvc)中需要实现文件上传,而自己对java文件上传这一块未接触过,且对Http协议较模糊,故这次采用渐进的方式来学习文件上传的原理与实践。该博客重在实践。一.Http协议原理简介   HTTP是一个属于应用层的面向对象的协议,由于其简捷、快速的方式,适用于分布式超媒体信息系统。它于1990年提出,经过几年的使用与发展,

发表回复

您的电子邮箱地址不会被公开。

关注全栈程序员社区公众号