68a301dcba3db85c46247d29857465c0
Flutter 状态管理 0x02 - Isolates && Event Loops

前言

前两篇文章:

如果你还没有阅读前面的文章的话我还是建议先阅读或者了解一下相关知识,因为专栏是按照顺序写的,有时候难免会假定读者已经看过之前文章介绍过的内容。

Flutter 实际开发中总会接触到一些异步编程(比如:网络请求),通常会以 Future<T> 的形式封装这些异步逻辑的返回结果。而 Flutter 开发所使用的 Dart 语言却是单线程模式的,那么单线程是如何实现异步编程的呢?Dart 中的多线程编程又应该怎么写呢?

索引

  • Dart 异步编程
  • Event Loop
  • Isolate
  • 使用合适的异步方式

Dart 异步编程

Dart 如何做到单线程异步

众所周知,Flutter 只是一个跨平台的 UI 库,而 Dart 才是我们用 Flutter 开发时使用的语言。尽管 Dart 作为一种单线程语言却提供了诸如 Future, Steam 等异步编程能力,同时还提供了 async/await 语法糖。那么它是怎么做到的呢?

Event Loop,Dart 之所以可以在单线程支持异步编程完全是因为 Event Loop。这里可以先简单把它理解成为一个无限事件处理循环,伪代码可以是(其实这里忽略了很多东西,比如微任务):

while (event != exit) {
    process(event);
    event = event->next;
}

如你所想它是一个 FIFO 队列,我们在开发中写好的代码逻辑(比如:按下按钮、Futrue.then())会在用户触发相应手势后被分发到 Event Loop 中按顺序执行。

Dart 中的多线程

当一个相对复杂的逻辑需要异步时如果还用 Future 往 Event Loop 里面怼的话会造成 Event Loop 后续 Event 得不到及时处理,直观感受的话就是界面卡顿。那么 Dart 中如何多线程编程呢?

Isolate,Dart 中可以通过创建一个 Isolate 实例来创建线程,每个 Isolate 创建成功之后有与之对应的 Event Loop。

Emmmmm...通过 Isolate 实现多线程编程并不同于我们在 Native 开发中完全一样,或者说...非常不一样!

Isolate 和它的名字一样,是与其他 Isolate 隔离开的,每一个 Isolate 都有完全独立的上下文,多个 Isolate 之间通信依赖消息发送。

从某种意义上看,其实 Isolate 的设计更像是进程,反倒是 Event Loop 在单线程上做执行函数调度配合 async/await 关键字的使用体验更贴近线程。

Event Loop

当一个 Flutter 应用启动后会自动创建一个主 Isolate,创建之后 Dart 会自动做以下事:

  1. 初始化 MicroTaskEvent 两个 FIFO 队列
  2. 执行 main() 函数
  3. 开启 Event Loop

Event Loop 是这个主 Isolate 生命周期中不可见的处理逻辑,它通过 MicroTaskEvent 分发调度我们的代码执行顺序。如上文所介绍的一样,Event Loop 对应一个无限循环,由一个内部时钟进行节奏控制,如果没有其他 Dart 代码正在执行,则在每个时钟滴答执行一下操作:

void eventLoop(){
    while (microTaskQueue.isNotEmpty) {
        fetchFirstMicroTaskFromQueue();
        executeThisMicroTask();
        return;
    }

    if (eventQueue.isNotEmpty) {
        fetchFirstEventFromQueue();
        executeThisEventRelatedCode();
    }
} 

Note: 正如我们看到的,Event Loop 会先处理 MicroTask 队列中的微任务,之后才轮到 Event

MicroTask Queue

MicroTask Queue 作为 Event Loop 中高优执行队列,适用于非常短的异步处理逻辑,以便可以在完成逻辑之后可以让 Event Loop 立即回头处理 Event Queue 中的事件逻辑。

top Created with Sketch.