Dart的事件循环如下图所示。和JavaScript的基本一样。循环中有两个队列。一个是微任务队列(MicroTask queue),一个是事件队列(Event queue)。
- 事件队列包含外部事件,例如I/O,
Timer
,绘制事件等等。 - 微任务队列则包含有Dart内部的微任务,主要是通过
scheduleMicrotask
来调度。
Dart的事件循环的运行遵循以下规则:
- 首先处理所有微任务队列里的微任务。
- 处理完所有微任务以后。从事件队列里取1个事件进行处理。
- 回到微任务队列继续循环。
注意第一步里的所有,也就是说在处理事件队列之前,Dart要先把所有的微任务处理完。如果某一时刻微任务队列里有8个微任务,事件队列有2个事件,Dart也会先把这8个微任务全部处理完再从事件队列中取出1个事件处理,之后又会回到微任务队列去看有没有未执行的微任务。
总而言之,就是对微任务队列是一次性全部处理,对于事件队列是一次只处理一个。
这个流程要清楚,清楚了才能理解Dart代码的执行顺序。
异步执行
那么在Dart中如何让你的代码异步执行呢?很简单,把要异步执行的代码放在微任务队列或者事件队列里就行了。
- 可以调用
scheduleMicrotask
来让代码以微任务的方式异步执行
scheduleMicrotask((){
print(‘a microtask’);
});
- 可以调用
Timer.run
来让代码以Event的方式异步执行
Timer.run((){
print(‘a event’);
});
好了,现在你知道怎么让你的Dart代码异步执行了。看起来并不是很复杂,但是你需要清楚的知道你的异步代码执行的顺序。这也是很多前端面试时候会问到的问题。举个简单的例子,请问下面这段代码是否会输出"executed"?
main() {
Timer.run(() { print(“executed”); });
foo() {
scheduleMicrotask(foo);
}
foo();
}
答案是不会,因为在始终会有一个foo
存在于微任务队列。导致Event Loop没有机会去处理事件队列。还有更复杂的一些例子会有大量的异步代码混合嵌套起来然后问你执行顺序是什么样的,这都需要按照上述Event Loop规则仔细去分析。
和JS一样,仅仅使用回调函数来做异步的话很容易陷入“回调地狱(Callback hell)”,为了避免这样的问题,JS引入了Promise
。同样的, Dart引入了Future
。
Future
要使用Future
的话需要引入dart.async
import ‘dart:async’;
Future
提供了一系列构造函数供你选择。
创建一个立刻在事件队列里运行的Future
:
Future(() => print(‘立刻在Event queue中运行的Future’));
创建一个延时1秒在事件队列里运行的Future
:
Future.delayed(const Duration(seconds:1), () => print(‘1秒后在Event queue中运行的Future’));
创建一个在微任务队列里运行的Future
:
Future.microtask(() => print(‘在Microtask queue里运行的Future’));
创建一个同步运行的Future:
Future.sync(() => print(‘同步运行的Future’));
对,你没看错,同步运行的。
这里要注意一下,这个同步运行指的是构造
Future
的时候传入的函数是同步运行的,这个Future
通过then
串进来的回调函数是调度到微任务队列异步执行的。
有了Future
之后, 通过调用then
来把回调函数串起来,这样就解决了"回调地狱"的问题。
Future(()=> print(‘task’))
.then(()=> print(‘callback1’))
.then(()=> print(‘callback2’));
在task打印完毕以后,通过then
串起来的回调函数会按照链接的顺序依次执行。 如果task执行出错怎么办?你可以通过catchError
来链上一个错误处理函数:
Future(()=> throw ‘we have a problem’)
.then(()=> print(‘callback1’))
.then(()=> print(‘callback2’))
.catchError((error)=>print(‘$error’));
上面这个Future
执行时直接抛出一个异常,这个异常会被catchError
捕捉到。类似于Java中的try/catch
机制的catch
代码块。运行后只会执行catchError
里的代码。两个then
中的代码都不会被执行。
既然有了类似Java的try/catch
,那么Java中的finally
也应该有吧。有的,那就是whenComplete
:
Future(()=> throw ‘we have a problem’)
.then(()=> print(‘callback1’))
.then(()=> print(‘callback2’))
.catchError((error)=>print(‘$error’))
.whenComplete(()=> print(‘whenComplete’));
无论这个Future
是正常执行完毕还是抛出异常,whenComplete
都一定会被执行。
自我介绍一下,小编13年上海交大毕业,曾经在小公司待过,也去过华为、OPPO等大厂,18年进入阿里一直到现在。
深知大多数Android工程师,想要提升技能,往往是自己摸索成长或者是报班学习,但对于培训机构动则几千的学费,着实压力不小。自己不成体系的自学效果低效又漫长,而且极易碰到天花板技术停滞不前!
因此收集整理了一份《2024年Android移动开发全套学习资料》,初衷也很简单,就是希望能够帮助到想自学提升又不知道该从何学起的朋友,同时减轻大家的负担。
既有适合小白学习的零基础资料,也有适合3年以上经验的小伙伴深入学习提升的进阶课程,基本涵盖了95%以上Android开发知识点,真正体系化!
由于文件比较大,这里只是将部分目录大纲截图出来,每个节点里面都包含大厂面经、学习笔记、源码讲义、实战项目、讲解视频,并且后续会持续更新
如果你觉得这些内容对你有帮助,可以添加V:vip204888 备注Android获取(资料价值较高,非无偿)
最后
由于文章篇幅原因,我只把面试题列了出来,详细的答案,我整理成了一份PDF文档,这份文档还包括了还有 高级架构技术进阶脑图、Android开发面试专题资料,高级进阶架构资料 ,帮助大家学习提升进阶,也节省大家在网上搜索资料的时间来学习。
1711559287110)]
最后
由于文章篇幅原因,我只把面试题列了出来,详细的答案,我整理成了一份PDF文档,这份文档还包括了还有 高级架构技术进阶脑图、Android开发面试专题资料,高级进阶架构资料 ,帮助大家学习提升进阶,也节省大家在网上搜索资料的时间来学习。