Flutter 事件机制 - Future 和 MicroTask 全解析

写在前面

了解过Flutter的同窗都知道,不一样于 Android 原生开发,dart 是单线程实体的语言,因此咱们通常的异步操做,实际上仍是经过单线程经过调度任务优先级来实现的,就是咱们常常用到的 Future,可是Flutter中的事件机制到底是怎样的?多个Future 和 Microtask 程序的执行顺序是怎样的? 本文将借助两个比较复杂的例子来详细介绍 Flutter 的事件机制,但愿能对你们有所帮助。git

Main代码块,EventQueue,MicrotaskQueue 的执行优先级

首先我得提一嘴 isolate(隔离),isolate是有本身的内存和单线程控制的运行实体,isolate相似于线程。 运行中的 Flutter 程序由一个或多个 isolate 组成。咱们的代码默认都在 Main isolate中执行。
为了保持高的响应性,特别耗时的任务通常不要放在Main isolate 中。但 isolate 不是本文的重点,在此就不过多赘述。github

Dart 中事件机制的实现 :Main isolate 中有一个Looper,但存在两个Queue:Event Queue 和 Microtask Queue 。
由于 isolate 是单线程实体,因此 isolate中的代码是按顺序执行的。
因此 dart 中的代码执行优先级能够分为三个级别:
bash

  1. 在 Main 中写代码将最早执行;
  2. 执行完 Main 中的代码,而后会检查并执行 Microtask Queue 中的任务, 一般使用 scheduleMicrotask 将事件添加到 MicroTask Queue 中;
  3. 最后执行 EventQueue 队列中的代码,一般使用 Future 向 EventQueue加入时间,也可使用 async 和 await 向 EventQueue 加入事件。

总结:Dart 中事件的执行顺序:Main > MicroTask > EventQueue。
如图:app

验证:

void testSX(){
  new Future(() => print('s_1'));
  scheduleMicrotask(() => print('s_2'));
  print('s_3');
}
复制代码

输出结果:异步

I/flutter (32415): s_3
I/flutter (32415): s_2
I/flutter (32415): s_1
复制代码

Future简介

前面讲到,用 async 和 await 组合,便可向 event queue 中插入 event 实现异步操做,那为何还会有Future呢?
其实,Future 最主要的功能就是提供了链式调用。async

new Future (() => print('拆分任务_1'))
    .then((i) => print('拆分任务_2'))
    .then((i) => print('拆分任务_3'))
    .whenComplete(()=>print('任务完成'));
复制代码

Future中的 then 并无建立新的Event丢到Event Queue中,而只是一个普通的Function,在一个 Future 全部的 Function 执行完后,下一个 Future 才会开始执行。oop

多个 Future 的执行顺序

  1. 规则一:Future 的执行顺序为Future的在 EventQueue 的排列顺序。相似于 JAVA 中的队列,先来先执行。
  2. 规则二:当任务须要延迟执行时,可使用 new Future.delay() 来将任务延迟执行。
  3. 规则三: Future 若是执行完才添加 than ,该任务会被放入 microTask,当前 Future 执行完会执行 microTask,microTask 为空后才会执行下一个Future。
  4. 规则四:Future 是链式调用,意味着Future 的 then 未执行完,下一个then 不会执行。

理论结束,而后来看一段代码吧:ui

void testFuture() {
  Future f1 = new Future(() => print('f1'));
  Future f2 = new Future(() =>  null);
  Future f3 = new Future.delayed(Duration(seconds: 1) ,() => print('f2'));
  Future f4 = new Future(() => null);
  Future f5 = new Future(() => null);

  f5.then((_) => print('f3'));
  f4.then((_) {
    print('f4');
    new Future(() => print('f5'));
    f2.then((_) {
      print('f6');
    });
  });
  f2.then((m) {
    print('f7');
  });
  print('f8');
}
复制代码

各位同窗能够试着写一下结果,而后对比下输出结果。spa

输出结果:线程

com.example.flutter_dart_app I/flutter: f8
com.example.flutter_dart_app I/flutter: f1
com.example.flutter_dart_app I/flutter: f7
com.example.flutter_dart_app I/flutter: f4
com.example.flutter_dart_app I/flutter: f6
com.example.flutter_dart_app I/flutter: f3
com.example.flutter_dart_app I/flutter: f5
com.example.flutter_dart_app I/flutter: f2
复制代码

是否是跟本身的结果截然不同,别急,看我来慢慢分析: 分析:

  1. 首先执行Main 的代码,因此首先输出: 8;
  2. 而后参考上面的规则1,Future 1 到 5 是按初始化顺序放入 EventQueue中,因此依次执行Future 1到5 , 因此输出结果:8,1,7。
  3. 参考规则2,f3 延时执行,必定是在最后一个:8,1,7,…,2。
  4. 在 f4 中,首先输出 f4 :8,1,7,4,…,2。
  5. 在 f4 的 then 的方法块中,新建了Future, 因此新建的 Future 将在 EventQueue尾部,最后被执行:8,1,7,4,…,5,2。
  6. 在 f4 的 then 的方法块中,给 f2 添加了 then ,但此时 f2 已经执行完了,参考规则三,因此 then 中的代码会被放到 microTask 中,在当前 Future 执行完后执行。 由于此时Future f4已经执行完了,因此会处理microTask(microTask优先级高)。结果:8,1,7,4,6,..,5,2。
  7. 此时咱们的 EventQueue 中还有 f5,和在 f4 中添加的新的Future。 因此咱们的最终结果就是:8,1,7,4,6,3,5,2。

是否是有点理解不了,没事,牢记四个规则,本身再算一遍,相信你就了然于胸了。重要要在脑海里有一个 EventQueue 的队列模型,牢记先进先出。

而后来试一试下一题:

多Future 和 多micTask 的执行顺序

void testScheduleMicrotatsk() {
  scheduleMicrotask(() => print('Mission_1'));

//注释1
  new Future.delayed(new Duration(seconds: 1), () => print('Mission_2'));

//注释2
  new Future(() => print('Mission_3')).then((_) {
    print('Mission_4');
    scheduleMicrotask(() => print('Mission_5'));
  }).then((_) => print('Mission_6'));

//注释3
  new Future(() => print('Mission_7'))
      .then((_) => new Future(() => print('Mission_8')))
      .then((_) => print('Mission_9'));

//注释4
  new Future(() => print('Mission_10'));

  scheduleMicrotask(() => print('Mission_11'));

  print('Mission_12');
}

复制代码

你们能够先本身试一下,再对照结果~

输出结果:

I/flutter (19025): Mission_12
I/flutter (19025): Mission_1
I/flutter (19025): Mission_11
I/flutter (19025): Mission_3
I/flutter (19025): Mission_4
I/flutter (19025): Mission_6
I/flutter (19025): Mission_5
I/flutter (19025): Mission_7
I/flutter (19025): Mission_10
I/flutter (19025): Mission_8
I/flutter (19025): Mission_9
Syncing files to device MIX 3...
I/flutter (19025): Mission_2
复制代码

是否是仍是没答全对?不要紧,很正常,看我慢慢道来:
分析:

  1. 根据 Main > MicroTask > EventQueue。咱们首先会获得输出结果:12,1,11。
  2. 注释1 的 Future 是延时执行,因此:12,1,11,…,2。
  3. 注释2 中建立了 Microtask,Microtask会在该Future执行完后执行,因此:12,1,11,4,6,5,…,2。
  4. 重点来了。咱们在注释3 的Future 的 then 中新建了Future(输出Mission_8),新建的 Future 将被加到 EventQueue尾部,而且,注释3的Future后续的then将再也不执行,由于这个链被阻塞了!
    注意对比上一题中的 f4, 上一题中的 f4 是一个 than 方法包裹了代码块。
    此时的结果:12,1,11,4,6,5,7,…,2。
  5. 执行完注释4 的 Future,而后会执行咱们在注释3 Future 新加入的 Future,以后注释3 的Future再也不阻塞,会继续执行,结果: 12,1,11,4,6,5,7,10,8,9,2。

看到这里,相信各位同窗已经对 Dart 事件机制有一个大概的了解,但愿能对 各位在学Flutter 的同窗有所帮助,蟹蟹~

END

我是雷加,若是您喜欢个人文章,请留下你的赞;若有疑问和建议,请在评论区留言
个人 Github, 欢迎关注~

相关文章
相关标签/搜索