Dart是单线程模型,而Flutter则依赖于Dart,单线程模型有一个问题:同一时间执行一个操作,而其他的操作只能再其之后执行。

我们知道在Android中不能写死循环,否则会导致ANR,而Flutter也是一样,在Dart中如果我们写一个很大的for循环,那么在循环中执行操作同样会导致线程的阻塞,界面也被阻塞,例如在重写的setState()中执行循环,则必须等到结束后才能加载出界面。

但是在如今纷繁复杂的业务逻辑要求中,我们单线程模型实际上很难满足各种各样的需求了。所以,Dart采用了了一个代码序列器(事件循环)。

当我们启动一个DartApp时,将会构建一个新的线程进程,在Dart中为Isolate,该线程将是你在整个应用中唯一需要关注的。

所以,此线程创建后,Dart将会自动地:

  1. 初始化2个FIFO队列(MicroTask和Event)

  2. 并且当该方法执行完成后,执行Main方法

  3. 启动事件循环

事件循环是一种无限循环,在每个时钟周期内,如果没有其他的Dart代码执行,则:

void eventLoop(){

while (microTaskQueue.isNotEmpty){

fetchFirstMicroTaskFromQueue();

executeThisMicroTask();

return;

}

if (eventQueue.isNotEmpty){

fetchFirstEventFromQueue();

executeThisEventRelatedCode();

}

}

从先后顺序我们可以看出,MicoTask队列优先于Event队列

5.1 MicroTask队列

MicroTask队列用于非常简短且需要异步执行的的内部动作,这些动作需要在其他事件完成后 并 在将执行权交给Event队列之前运行。

5.2 Event队列

Event 队列适用于以下参考模型:

  • IO

  • 手势

  • 绘图

  • 计时器

  • futures

事实上,每次外部事件被触发时,需要执行的代码都会被Event队列所引用。一旦没有MicroTask运行,事件循环将考虑Event队列中的第一项并执行它,而Future操作也将由Event队列执行。

5.3 Future

Future是一个异步执行并且在未来某一个时刻完成或者失败的任务,当实例化一个Future时:

  • 该Future的实例被创建、并记录在由Dart管理的内部数组中。

  • 需要由此Future执行的代码直接推送到Event中。

  • 该Future实例返回一个状态(=incomplete)

  • 如果存在下一个同步代码,则执行它。

只要事件循环Event循环中获取它,被Future引用的代码将像其他任何Event一样执行。

当改代码将被执行完成(或者失败)时,then或者cacheError回调将被触发。

在如下例子中:

void main(){

print(‘Before the Future’);

Future((){

print(‘Running the Future’);

}).then((_){

print(‘Future is complete’);

});

print(‘After the Future’);

}

输出的顺序:

Before the Future

After the Future

Running the Future

Future is complete

执行的流程:

  1. print(‘Before the Future’)

  2. 将 (){print(‘Running the Future’);} 添加到 Event 队列;

  3. print(‘After the Future’)

  4. 事件循环获取(在第二步引用的)代码并执行它

  5. 当代码执行时,它会查找 then() 语句并执行它

所以,Flutter/Dart是使用Event循环机制来模拟并发的请求的。

Aysnc方法在使用时,Dart会认为该方法的返回值是一个Future,它同步执行该方法,直到遇到第一个await关键字,然后它暂停该方法其他部分的执行,一旦await关键字引用的Future执行完成,下一行代码将立即执行。

例如这个例子:

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方法开始执行,遇到第一个await则暂停,按照以往的认知,打印应该是:

A

B start

C start from B

C running Future from B

C end of Future from B

C end from B

B end

C start from A

C running Future from A

C end of Future from A

C end from A

D

但是其实是:

A

B start

C start from B

C end from B

— C中的Future代码会在之后执行,不会立即执行。

B end

C start from main

C end from main

D

—到此处代码执行完了,才开始执行Event中的代码

C running Future from B

C end of Future from B

C running Future from main

C end of Future from main

这和我们想象的多线程(异步)处理有点不一样,异步只是线程各自以未知的顺序向前推进,但是单线程的Dart依靠事件循环机制,模拟了异步操作,但是我们发现所有的Future都放到了代码的最后执行。预测程序执行变得非常困难。

我们又知道,await会阻塞在当前代码的位置,所以,await和Future配合使用,可以获得同步的效果,即该代码等到Future执行完了再向下执行:

methodC(String from) async {

print(‘C start from $from’);

await Future((){ // <== 在此处进行修改

print(‘C running Future from $from’);

}).then((_){

print(‘C end of Future from $from’);

});

print(‘C end from $from’);

}

这样一来,可能在C start之后,等到C执行完成再向下执行。

所以,Dart中的异步执行实际上只是按照Event的事件处理规则执行,并不是真正的异步执行:

EvnetOfFlutter.png

自我介绍一下,小编13年上海交大毕业,曾经在小公司待过,也去过华为、OPPO等大厂,18年进入阿里一直到现在。

深知大多数初中级Android工程师,想要提升技能,往往是自己摸索成长或者是报班学习,但对于培训机构动则近万的学费,着实压力不小。自己不成体系的自学效果低效又漫长,而且极易碰到天花板技术停滞不前!

因此收集整理了一份《2024年Android移动开发全套学习资料》,初衷也很简单,就是希望能够帮助到想自学提升又不知道该从何学起的朋友,同时减轻大家的负担。

img

img

img

img

既有适合小白学习的零基础资料,也有适合3年以上经验的小伙伴深入学习提升的进阶课程,基本涵盖了95%以上Android开发知识点,真正体系化!

由于文件比较大,这里只是将部分目录截图出来,每个节点里面都包含大厂面经、学习笔记、源码讲义、实战项目、讲解视频,并且会持续更新!

如果你觉得这些内容对你有帮助,可以扫码获取!!(备注:Android)

面试复习笔记

这份资料我从春招开始,就会将各博客、论坛。网站上等优质的Android开发中高级面试题收集起来,然后全网寻找最优的解答方案。每一道面试题都是百分百的大厂面经真题+最优解答。包知识脉络 + 诸多细节。
节省大家在网上搜索资料的时间来学习,也可以分享给身边好友一起学习。

《960页Android开发笔记》

《1307页Android开发面试宝典》

包含了腾讯、百度、小米、阿里、乐视、美团、58、猎豹、360、新浪、搜狐等一线互联网公司面试被问到的题目。熟悉本文中列出的知识点会大大增加通过前两轮技术面试的几率。

《507页Android开发相关源码解析》

只要是程序员,不管是Java还是Android,如果不去阅读源码,只看API文档,那就只是停留于皮毛,这对我们知识体系的建立和完备以及实战技术的提升都是不利的。

真正最能锻炼能力的便是直接去阅读源码,不仅限于阅读各大系统源码,还包括各种优秀的开源库。

《互联网大厂面试真题解析、进阶开发核心学习笔记、全套讲解视频、实战项目源码讲义》点击传送门即可获取!

了腾讯、百度、小米、阿里、乐视、美团、58、猎豹、360、新浪、搜狐等一线互联网公司面试被问到的题目。熟悉本文中列出的知识点会大大增加通过前两轮技术面试的几率。

[外链图片转存中…(img-fb6xNfEK-1713250843245)]

《507页Android开发相关源码解析》

只要是程序员,不管是Java还是Android,如果不去阅读源码,只看API文档,那就只是停留于皮毛,这对我们知识体系的建立和完备以及实战技术的提升都是不利的。

真正最能锻炼能力的便是直接去阅读源码,不仅限于阅读各大系统源码,还包括各种优秀的开源库。

[外链图片转存中…(img-gmhyhECt-1713250843247)]

《互联网大厂面试真题解析、进阶开发核心学习笔记、全套讲解视频、实战项目源码讲义》点击传送门即可获取!

Logo

开源鸿蒙跨平台开发社区汇聚开发者与厂商,共建“一次开发,多端部署”的开源生态,致力于降低跨端开发门槛,推动万物智联创新。

更多推荐