Flutter 事件机制 – Future 和 MicroTask 全解析
写在前面
理解过Flutter的同学都知道,不同于 Android 原生开发,dart 是单线程实体的语言,所以我们一般的异步操作,实际上还是通过单线程通过调度任务优先级来实现的,就是我们经常用到的 Future,但是Flutter中的事件机制到底是怎么的?多个Future 和 Microtask 程序的执行顺序是怎么的? 本文将借助两个比较复杂的例子来详细详情 Flutter 的事件机制,希望能对大家有所帮助。
Main代码块,EventQueue,MicrotaskQueue 的执行优先级
首先我得提一嘴 isolate(隔离),isolate是有自己的内存和单线程控制的运行实体,isolate相似于线程。 运行中的 Flutter 程序由一个或者多个 isolate 组成。我们的代码默认都在 Main isolate中执行。
为了保持高的响应性,特别耗时的任务一般不要放在Main isolate 中。但 isolate 不是本文的重点,在此就不过多赘述。
Dart 中事件机制的实现 :Main isolate 中有一个Looper,但存在两个Queue:Event Queue 和 Microtask Queue 。
由于 isolate 是单线程实体,所以 isolate中的代码是按顺序执行的。
所以 dart 中的代码执行优先级可以分为三个级别:
- 在 Main 中写代码将最先执行;
- 执行完 Main 中的代码,而后会检查并执行 Microtask Queue 中的任务, 通常使用 scheduleMicrotask 将事件增加到 MicroTask Queue 中;
- 最后执行 EventQueue 队列中的代码,通常使用 Future 向 EventQueue加入时间,也可以使用 async 和 await 向 EventQueue 加入事件。
总结:Dart 中事件的执行顺序:Main > MicroTask > EventQueue。
如图:
image.png
验证:
void testSX(){ new Future(() => print('s_1')); scheduleMicrotask(() => print('s_2')); print('s_3');}输出结果:
I/flutter (32415): s_3I/flutter (32415): s_2I/flutter (32415): s_1Future简介
前面讲到,用 async 和 await 组合,就可向 event queue 中插入 event 实现异步操作,那为什么还会有Future呢?
其实,Future 最主要的功能就是提供了链式调用。
new Future (() => print('拆分任务_1')) .then((i) => print('拆分任务_2')) .then((i) => print('拆分任务_3')) .whenComplete(()=>print('任务完成'));Future中的 then 并没有创立新的Event丢到Event Queue中,而只是一个普通的Function,在一个 Future 所有的 Function 执行完后,下一个 Future 才会开始执行。
多个 Future 的执行顺序
- 规则一:Future 的执行顺序为Future的在 EventQueue 的排列顺序。相似于 JAVA 中的队列,先来先执行。
- 规则二:当任务需要推迟执行时,可以使用 new Future.delay() 来将任务推迟执行。
- 规则三: Future 假如执行完才增加 than ,该任务会被放入 microTask,当前 Future 执行完会执行 microTask,microTask 为空后才会执行下一个Future。
- 规则四:Future 是链式调用,意味着Future 的 then 未执行完,下一个then 不会执行。
理论结束,而后来看一段代码吧:
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');}各位同学可以试着写一下结果,而后比照下输出结果。
输出结果:
com.example.flutter_dart_app I/flutter: f8com.example.flutter_dart_app I/flutter: f1com.example.flutter_dart_app I/flutter: f7com.example.flutter_dart_app I/flutter: f4com.example.flutter_dart_app I/flutter: f6com.example.flutter_dart_app I/flutter: f3com.example.flutter_dart_app I/flutter: f5com.example.flutter_dart_app I/flutter: f2是不是跟自己的结果大相径庭,别急,看我来慢慢分析: 分析:
- 首先执行Main 的代码,所以首先输出: 8;
- 而后参考上面的规则1,Future 1 到 5 是按初始化顺序放入 EventQueue中,所以依次执行Future 1到5 , 所以输出结果:8,1,7。
- 参考规则2,f3 延时执行,肯定是在最后一个:8,1,7,…,2。
- 在 f4 中,首先输出 f4 :8,1,7,4,…,2。
- 在 f4 的 then 的方法块中,新建了Future, 所以新建的 Future 将在 EventQueue尾部,最后被执行:8,1,7,4,…,5,2。
- 在 f4 的 then 的方法块中,给 f2 增加了 then ,但此时 f2 已经执行完了,参考规则三,所以 then 中的代码会被放到 microTask 中,在当前 Future 执行完后执行。 由于此时Future f4已经执行完了,所以会解决microTask(microTask优先级高)。结果:8,1,7,4,6,..,5,2。
- 此时我们的 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_12I/flutter (19025): Mission_1I/flutter (19025): Mission_11I/flutter (19025): Mission_3I/flutter (19025): Mission_4I/flutter (19025): Mission_6I/flutter (19025): Mission_5I/flutter (19025): Mission_7I/flutter (19025): Mission_10I/flutter (19025): Mission_8I/flutter (19025): Mission_9Syncing files to device MIX 3...I/flutter (19025): Mission_2是不是还是没答全对?没关系,很正常,看我慢慢道来:
分析:
- 根据 Main > MicroTask > EventQueue。我们首先会得到输出结果:12,1,11。
- 注释1 的 Future 是延时执行,所以:12,1,11,…,2。
- 注释2 中创立了 Microtask,Microtask会在该Future执行完后执行,所以:12,1,11,4,6,5,…,2。
- 重点来了。我们在注释3 的Future 的 then 中新建了Future(输出Mission_8),新建的 Future 将被加到 EventQueue尾部,并且,注释3的Future后续的then将不再执行,由于这个链被阻塞了!
注意比照上一题中的 f4, 上一题中的 f4 是一个 than 方法包裹了代码块。
此时的结果:12,1,11,4,6,5,7,…,2。 - 执行完注释4 的 Future,而后会执行我们在注释3 Future 新加入的 Future,之后注释3 的Future不再阻塞,会继续执行,结果: 12,1,11,4,6,5,7,10,8,9,2。
看到这里,相信各位同学已经对 Dart 事件机制有一个大概的理解,希望能对 各位在学Flutter 的同学有所帮助,蟹蟹~
END
【附】相关架构及资料
加群 Android IOC架构设计领取获取往期Android高级架构资料、源码、笔记、视频。高级UI、性能优化、架构师课程、NDK、混合式开发(ReactNative+Weex)微信小程序、Flutter全方面的Android进阶实践技术,群内还有技术大牛一起探讨交流处理问题。
image
领取方式:
点赞+加群免费获取 Android IOC架构设计
1. 本站所有资源来源于用户上传和网络,如有侵权请邮件联系站长!
2. 分享目的仅供大家学习和交流,您必须在下载后24小时内删除!
3. 不得使用于非法商业用途,不得违反国家法律。否则后果自负!
4. 本站提供的源码、模板、插件等等其他资源,都不包含技术服务请大家谅解!
5. 如有链接无法下载、失效或广告,请联系管理员处理!
6. 本站资源售价只是摆设,本站源码仅提供给会员学习使用!
7. 如遇到加密压缩包,请使用360解压,如遇到无法解压的请联系管理员
开心源码网 » Flutter 事件机制 – Future 和 MicroTask 全解析