0
点赞
收藏
分享

微信扫一扫

Android开发—Flutter 中的事件驱动【附,阿里P8大佬亲自讲解

public final void runOnUiThread(Runnable action) {

if (Thread.currentThread() != mUiThread) {

mHandler.post(action);

} else {

action.run();

}

}

判断一下当前线程是否主线程,是的话直接执行,否则的话,通过Handler机制,post到主线程,然后由子线程的Looper取出执行。

比如我们在请求网络后,想让系统加载一个数据,数据返回后,更新视图,那么“数据返回”实际上就是一个事件,既然是事件我们肯定要消费,所以就调用runOnUiThread交给主线程消费。

其实,我们在任何一个主线程的调用栈中,调用栈底的方法一定是loop方法,因为所有发生在主线程的操作都是先给主线程的MessageQueue加入一个Message,然后looper取出执行操作,Message甚至可以附带一个Runnable来执行代码。也可以附带一些信息,在回调处统一处理。

[]( )3. OnClickListener 事件

====================================================================================

我们通常会调用View下的setOnClickListener设定点击事件,比较常见的写法除了简单的设置View.OnClickListenerXML指定以外,通常是使用当前的Activity去实现View.OnClickListener接口,重写onClick方法,根据ID来判断点击事件产生的对象,进而确定具体的点击事件。

比如设置一个按钮,我们点击按钮就要请求网络,那么点击事件就会作为请求网络的驱动,这就是一个非常简单的事件驱动的流程。

[]( )4. 事件驱动模型

========================================================================

事件驱动模型有三个要素:事件源监听器事件。熟悉设计模式的同学应该很快就能反应过来,这三要素和Observer模式中的三个构成非常相似。实际上事件驱动模型就是基于观察者而定制的。

事件驱动模型的工作步骤:

  1. 定义监听器,为每一个事件编写处理方法。

  2. 监听器对象注册给事件源

  3. 事件源发生某个事件时,调用监听器中对应的方法完成事件的处理。

以上的3步,在OnClick事件中,分别对应:

//1. 监听器,处理响应事件

val events = View.OnClickListener {

Toast.makeText(this@MainActivity,"HelloWorld!",Toast.LENGTH_SHORT).show()

}

//2. 注册到事件源

findViewById<TextView>(R.id.tv).setOnClickListener (events)

//

Android开发—Flutter 中的事件驱动【附,阿里P8大佬亲自讲解

3. 当我们手指点击屏幕,产生事件时(即事件源产生事件),就向着目标分发事件,最终被触摸到的View所消费。

[]( )5. Dart和Flutter

==============================================================================

(这部分的内容主要来自[泪已无痕:[译] Flutter 异步编程:Future、Isolate 和事件循环]( ),原文更详细,这里是完全参考着他写的,详细了解建议看原文。)

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循环机制来模拟并发的请求的。

写在最后

最后我想说:对于程序员来说,要学习的知识内容、技术有太多太多,要想不被环境淘汰就只有不断提升自己,从来都是我们去适应环境,而不是环境来适应我们!

这里附上上述的技术体系图相关的几十套腾讯、头条、阿里、美团等公司2021年的面试题,把技术点整理成了视频和PDF(实际上比预期多花了不少精力),包含知识脉络 + 诸多细节,由于篇幅有限,这里以图片的形式给大家展示一部分。

相信它会给大家带来很多收获:

Android开发—Flutter 中的事件驱动【附,阿里P8大佬亲自讲解

Android开发—Flutter 中的事件驱动【附,阿里P8大佬亲自讲解

当程序员容易,当一个优秀的程序员是需要不断学习的,从初级程序员到高级程序员,从初级架构师到资深架构师,或者走向管理,从技术经理到技术总监,每个阶段都需要掌握不同的能力。早早确定自己的职业方向,才能在工作和能力提升中甩开同龄人。

举报

相关推荐

0 条评论