Event Loop事件循环
定义:
1. Flutter的事件循环是基于Dart语言的单线程事件驱动模型。它使用一个事件队列来接收和处理各种输入事件,包括用户交互、定时器、网络响应等。事件循环会按照事件的优先级和顺序依次处理这些事件。
2. 当一个事件被触发时,它会被放入事件队列中。事件循环会不断地从队列中取出事件,并将事件分发给相应的处理程序。
一、 问:Flutter 单线程的 Dart 为何能够流程运行 UI :
答:异步 IO + 事件循环
void main{
Event loop:保证事件循环一直运作:
}
二、 事件循环的核心组件包括:
事件队列(Event Queue)+Microtask队列
三、 事件队列:Event Queue
1. 事件队列用于存储各种类型的事件,包括用户输入事件、定时器事件、网络响应事件等。当一个事件发生时,它会被添加到事件队列中,等待事件循环的处理。
2. 采用先进先出(FIFO)的原则,即最先进入队列的事件会最先被处理。
四、 微任务:Microtask Queue
1. 是一种任务调度的机制,它允许在当前事件循环中执行延迟的、优先级较高的任务。
2. 微任务通常用于处理一些轻量级的操作,例如处理 Future 的完成回调、处理 Dart 的计时器回调等。在 Flutter 中,微任务被用于执行一些高优先级的任务,以保证响应性和界面的流畅性。
五、 执行过程:
1. Event loop 会在 main() 函数执行完毕后执行,事件循环开始。
2. 首先检查 Microtask Queue 队列中是否有等待的任务,如果Microtask队列中有待处理的任务,事件循环会立即处理Microtask队列中的任务,直到Microtask队列为空。
3. 如果Microtask队列为空,事件循环会继续检查Event队列。如果Event队列中有待处理的事件,事件循环会按照FIFO的顺序,逐个处理Event队列中的事件。
4. 如果Event队列为空,事件循环会等待下一个新的事件到达,然后重复上述过程。
5. 一旦两个队列都是空的,并且没有更多的事件发生,应用便会退出。但是在任务执行的过程中也可以插入新的微任务和事件任务,在这种情况下,整个线程的执行过程便是一直在循环,不会退出,而在 Flutter 中,主线程的执行过程正是如此,永不终止。
6. 当然,如果 app 的用户在 event loop 循环的过程中退出了 app,那么应用也会退出,不会执行队列中剩下的任务。
● 值得留意的是,当 event loop 从微任务队列中执行任务时,事件队列就会阻塞:应用不能绘制图形、处理用户点击、响应I/O操作等等。也就是说,微任务处理耗时过长的话,会导致应用程序的掉帧,降低用户体验。
六、 事件循环与微任务区别和联系:
1. 事件循环是一个持续运行的循环,负责接收、分发和处理各种事件,包括用户输入事件、定时器事件等。
2. 微任务是一种特殊的任务调度机制,用于在当前事件循环中执行延迟的、优先级较高的任务。
3. 事件循环负责整个应用程序的事件处理和调度,而微任务则是在事件循环中处理特定任务的机制。
4. 微任务通常比事件循环中的任务优先级更高,因此在事件循环的处理过程中,会首先执行微任务。
5. 在 Flutter 中,事件循环和微任务共同协作,确保事件的有序处理和高优先级任务的及时执行。事件循环负责接收和分发事件,而微任务则提供了一种机制来处理高优先级的任务,以保持界面的响应性和流畅性。
七、 事件队列与微任务区别和联系:
在Flutter中,事件队列(Event Queue)和微任务(Microtask)队列是两个不同的概念,它们具有一些区别和联系。
1. 区别:
a. 类型和用途:事件队列用于存储各种类型的事件,例如用户输入事件、定时器事件、网络响应事件等。它采用先进先出(FIFO)的原则,按照事件发生的顺序进行处理。而微任务队列是用于处理高优先级任务的队列,例如异步操作的回调、Future完成时的回调等。
b. 执行时机:事件队列中的事件在事件循环中按照顺序被处理,当事件循环检查到事件队列中有待处理的事件时,会触发相应的事件处理程序。而微任务队列的任务会在事件队列中的事件处理完成之后立即执行,即在事件循环的"空闲时间"内立即执行。
c. 执行优先级:事件队列中的事件具有一般的优先级,按照FIFO顺序执行。而微任务队列中的任务具有更高的优先级,会在事件队列中的事件处理之前优先执行。
2. 联系:
a. 都是任务队列:事件队列和微任务队列都是用于存储待处理的任务或事件的数据结构。
b. 同属事件循环:事件队列和微任务队列都是在Flutter的事件循环机制中使用的,用于管理任务和事件的执行顺序。
c. 异步操作的关联:微任务队列常用于处理异步操作的回调,例如Future完成时的回调。在执行异步操作期间,可以将任务添加到微任务队列中,在合适的时机执行这些任务。
八、 Flutter 事件队列使用场景:
在Flutter中,事件队列(Event Queue)用于存储各种类型的事件,例如用户交互事件、定时器事件、网络响应事件等。下面是一些常见的使用事件队列的场景:
1. 用户交互事件处理:Flutter应用程序需要响应用户的交互事件,例如点击按钮、滑动屏幕等。这些事件会被添加到事件队列中,并按照先进先出(FIFO)的原则进行处理。通过事件队列,可以确保按照事件发生的顺序依次处理用户的交互事件。
2. 定时器和动画:Flutter支持定时器和动画功能,用于实现定时执行任务和平滑的动画效果。通过事件队列,可以设置定时器,在指定的时间间隔后触发相应的定时器事件。定时器事件会被添加到事件队列中,然后由事件循环进行处理。
3. 网络请求和异步操作:在进行网络请求或其他异步操作时,通常会使用异步API(如Future、async/await等)来处理。这些异步操作会在完成时触发回调或返回Future对象,通过事件队列将回调或Future任务添加到事件队列中,以便在合适的时机执行。
4. 状态管理和界面更新:Flutter的UI框架会监听状态的改变,并根据需要更新应用程序的用户界面。当状态改变时,会通过事件队列将界面更新请求添加到事件队列中,然后由事件循环触发相应的界面更新。
5. 多线程和Isolate通信:Flutter支持多线程编程和Isolate(隔离线程)机制。在多线程或Isolate间进行通信时,可以使用类似消息队列的机制,将消息或事件添加到事件队列中,然后由事件循环进行处理和分发。
6. 响应系统级事件:Flutter应用程序可以响应系统级事件,例如设备方向改变、网络状态变化等。这些系统级事件会通过事件队列的机制,将事件添加到事件队列中,然后由应用程序进行处理。
总的来说,Flutter 应用程序的整个生命周期都依赖于事件循环机制,从接收用户输入到布局、绘制、动画和异步操作,都是通过事件循环进行协调和处理的。事件循环保证了事件的有序处理,并使得 Flutter 应用程序能够快速响应用户的交互和动态变化。
九、 Flutter 中常见的使用微任务的场景:
在Flutter中,微任务(Microtask)被广泛用于处理异步操作的回调和状态管理的相关任务。以下是一些常见的地方,在这些地方可以看到Flutter使用微任务的例子:
1. Future和async/await:在使用Future或async/await进行异步编程时,回调函数通常会被添加到微任务队列中,以便在事件队列中的事件处理完成后立即执行。
2. Widget生命周期:Flutter的Widget生命周期涉及到一系列的生命周期回调,例如initState、didUpdateWidget、dispose等。这些回调通常会使用微任务来确保在事件队列中的事件处理完成后立即执行。
3. Stream和StreamController:使用Stream和StreamController进行数据流的处理时,监听数据流的回调通常会被添加到微任务队列中。这样可以确保在事件队列中的事件处理完成后立即处理数据流的更新。
4. setState:在Flutter的状态管理中,使用setState方法更新状态会触发对应的状态更新回调。这些回调通常会被添加到微任务队列中,以确保在事件队列中的事件处理完成后立即进行状态更新。
5. 异常处理:在处理异常的时候,通常会使用try-catch语句捕获异常并执行相应的异常处理逻辑。异常处理逻辑通常会被添加到微任务队列中,以确保在事件队列中的事件处理完成后立即执行异常处理。
需要注意的是,微任务的执行优先级较高,但在使用微任务时也需要注意避免无限循环和长时间的阻塞,以免影响事件队列中事件的及时处理和界面更新。
总结来说,在Flutter中常见的使用微任务的地方包括异步操作的回调、Widget生命周期、Stream和StreamController的处理、setState方法的状态更新,以及异常处理等。通过微任务的机制,Flutter能够在事件队列中的事件处理完成后及时执行高优先级的任务,提高应用程序的响应性和效率。
以下是一个使用微任务的示例代码:
Future.delayed(Duration.zero, () {
print('Future');
});
scheduleMicrotask(() {
print('Microtask');
});
在上面的代码中,使用 Future.delayed() 方法来安排一个普通的异步任务,使用 scheduleMicrotask() 方法来安排一个微任务。由于微任务的优先级比普通异步任务更高,因此 'Microtask' 字符串将在 'Future' 字符串之前被打印出来。
除结束之前执行一些异步任务,可以使用微任务来实现。
十、 flutter 哪些方法可以添加事件队列
1. Timer类:Timer类提供了定时器功能,可以在指定的时间间隔后将任务添加到事件队列中。可以使用以下方式创建定时器:
Timer(Duration(milliseconds: 100), () {
// 任务逻辑
});
2. Future类:Future类提供了异步操作的功能,可以使用它的静态方法将任务添加到事件队列中。例如,使用Future.microtask()将任务添加到微任务队列中,使用Future.delayed()将任务添加到事件队列中的定时任务中。
3. WidgetsBinding类:WidgetsBinding是Flutter应用程序的绑定类,可以使用它注册观察者并在应用程序生命周期中的特定阶段执行任务。例如,可以使用WidgetsBinding.instance.addPostFrameCallback()在渲染完成后添加任务到事件队列中。
4. Stream类:Stream类表示一系列异步事件的流,可以通过监听Stream的方式将任务添加到事件队列中。当Stream中有新的事件产生时,相关的任务会被添加到事件队列中执行。
十一、 flutter 哪些方法可以添加微任务
在Flutter中,有几种方法可以添加微任务(Microtask):
1. scheduleMicrotask(): 这是Flutter提供的一个全局函数,用于将一个函数添加到微任务队列中。可以使用以下方式调用:
scheduleMicrotask(() {
// 微任务逻辑
});
2. Completer类:Completer是Flutter中用于创建Future的类,它也可以用来添加微任务。可以通过创建一个Completer对象并调用其complete方法来添加微任务,示例如下:
Completer<void> completer = Completer<void>();
completer.future.then((_) {
// 微任务逻辑
});
completer.complete();
3. async/await机制:使用async/await语法进行异步编程时,await关键字后面的代码会被封装为一个微任务,等待当前的事件队列中的任务执行完成后立即执行。示例如下:
Completer<void> completer = Completer<void>();
completer.future.then((_) {
// 微任务逻辑
});
completer.complete();
4. Future.microtask():用于将任务添加到微任务队列中,以便在当前事件循环中的任务执行完成后立即执行。
Future.microtask(() {
// 任务逻辑
});
当调用Future.microtask()时,传递的任务会被封装为一个微任务,并在当前事件循环中的任务执行完成后立即执行。与常规的Future任务不同,Future.microtask()中的任务具有更高的优先级,因此会在事件队列中的任务执行之前执行。
-----内容有错误欢迎指正--------