Flutter 事件传递机制

Flutter 状态管理原理

源码

Flutter run

image.png

事件循环与消息调度

在 Flutter 中,事件循环和消息调度机制是应用程序响应性和性能的关键。这个机制确保了异步操作的高效执行,同时保持了用户界面的流畅性。通过合理利用 Future 和 Isolate,开发者可以根据具体需求选择最适合的异步处理方式,从而优化应用程序的整体性能和用户体验。

事件循环:

       Microtask Queue 微任务队列:处理优先级高的异步任务  scheduleMicrotask;主任务执行后立马执行的队列

Event Queue 事件队列:处理普通异步任务,timer、io、用户输入;最低优先级,适用于用户事件,网络请求等

事件循环先处理微任务,处理完毕后再处理事件队列任务

graph LR
    classDef startend fill:#F5EBFF,stroke:#BE8FED,stroke-width:2px
    classDef process fill:#E5F6FF,stroke:#73A6FF,stroke-width:2px
    classDef decision fill:#FFF6CC,stroke:#FFBC52,stroke-width:2px

    A([开始事件循环迭代]):::startend --> B{微任务队列是否为空?}:::decision
    B -- 否 --> C(执行微任务队列中的所有任务):::process
    C --> B
    B -- 是 --> D{事件队列是否为空?}:::decision
    D -- 否 --> E(执行事件队列中的第一个任务):::process
    E --> A
    D -- 是 --> F([本次迭代结束]):::startend
    F -.-> A[开始事件循环迭代]:::startend

    style A stroke-dasharray: 5 5
    style F stroke-dasharray: 5 5
对比维度 事件队列 微任务队列
任务来源 来自异步操作回调,如浏览器中setTimeoutsetInterval、DOM事件(鼠标点击、键盘输入等),Node.js中的文件读写、网络请求等异步I/O操作完成后的回调函数 来自JavaScript语言本身异步操作,如Promise.then().catch().finally()方法回调,async/await相关回调,MutationObserver回调函数
执行时机 调用栈为空且微任务队列所有任务执行完毕后执行 每次事件循环迭代开始,先检查并执行微任务队列所有任务,直到队列为空,才处理事件队列任务
执行顺序 先进先出(FIFO) 先进先出(FIFO),且优先于事件队列执行
用途和场景 处理相对耗时、不紧急的异步操作,如网络请求、文件读写,避免阻塞主线程 用于当前任务完成后需尽快执行的操作,如更新UI状态、处理依赖异步操作结果的后续逻辑

Future 与then

await FutureFuture.then 的差异主要体现在语法和代码的可读性上,但它们的执行机制本质上是相同的,都是处理异步任务。以下是两者的简单对比:

  1. 语法与可读性
Future<void> example() async {
	var result = await someAsyncFunction();
}
Future<void> example() {
	someAsyncFunction().then((result) {
	});
}
  1. 执行顺序
  1. 错误处理
  1. 场景适用性

总结

await Future 更加符合人们的直觉,代码结构更清晰,尤其是当有多个异步任务时。Future.then 则更灵活,但可能导致回调地狱的情况。

Future 与 Isolate

特性 Future Isolate
设计目的 用于处理轻量级的异步操作,基于事件循环和微任务机制 用于并行执行重计算或长时间运行的任务,避免阻塞主线程
执行模型 在同一线程(主线程)中执行,利用微任务队列 协程(Coroutine) 在独立线程中执行,具有自己的内存空间和事件循环 多线程(multithreading)
内存管理 共享主线程内存 独立内存堆,需要通过消息传递实现通信,SendPort,ReceiverPort
性能 适合快速完成的异步任务,开销较小 需要创建销毁,涉及线程启动关闭,因此开销较大,但能显著提高计算密集型任务的性能
状态管理 通过 Futureasync/await 管理任务状态 通过消息传递(SendPort/ReceivePort)进行通信
错误处理 可以通过 catchErrortry/catch 处理 需要在消息传递中自行处理错误
适用场景 UI 更新、网络请求、文件 IO 等轻量级操作 数据处理、图像处理、音视频编解码等重计算

Isolate 基础