Dart 初学者,主要是自己学习使用。因为英语水平有限,基本都是靠谷歌翻译。大家可以去看原文:medium.com/dartlang/da… (好像需要墙)
正文
尽管 Dart 是单线程语言,但它提供 Future、Stream、后台任务以及其他特性用于编写现代异步程序以及响应式程序(Flutter)。
Isolates
一个 Isolate 就会运行着一个 Dart 的所有代码。就像机器上一个独立的小空间,拥有私有内存块和运行事件循环的单个线程

在许多其他语言(例如C ++)中,您可以让多个线程共享相同的内存并运行所需的任何代码。但 Dart 中每个线程在其自己的 Isolate 中,有自己的内存,而且这个线程只处理事件。
大多数的 Dart 应用将所有代码运行在一个 Isolate,当然如果你想增加多个 Isolate 也行。如果你需要大量的计算,这可能会使主 Isolate 丢帧,那你可以使用 Isolate.spawn() 或者 Flutter’s compute() function 去创建一个新的 Isolate 处理这类事务。让你的主 Isolate 专注于重建和渲染 widget 树。

新 Isolate 拥有自己的事件循环和内存,即使原始 Isolate 是该新 Isolate 的父级,也不允许其访问。这种机制正是 Isolate 名字的来源:内存块之间彼此隔离。
实际上,Isolate 可以一起工作的唯一方法是通过来回传递消息。一个 Isolate 向另一个发送消息,接收的 Isolate 使用其事件循环处理该消息。如下图所示

缺少共享内存听起来可能很严格,尤其是如果您使用的是Java或C ++之类的语言时,但这对Dart编码人员来说有一些关键的好处。
比如,Isolate 中内存分配和垃圾回收不需要锁定。Isolate 中只有一个线程,如果它不是很忙的话,内存并不会快速变化,所以不必锁定。这非常适合 Flutter 应用,它时常要迅速地构建和销毁 Widget 树。
原文:There’s only one thread, so if it’s not busy, you know the memory isn’t being mutated. 还不是很明白什么意思,后续搞明白了,再加上注释。
事件循环(Event loops)
现在你已经了解 Isolate 了,我们再来挖掘一下事件循环是如何让异步代码变成可能的吧。
想像一下应用沿着时间线的运行过程。应用启动,应用停止,之间发生一串串事件:磁盘 IO,用户手势以及类似一些事件。
你的应用无法预测这些事件的发生时间或发生顺序,因此必须使用一个永不阻塞的线程来处理所有事件。因此,该应用运行一个事件循环。它从事件队列中获取最旧的事件,进行处理,然后返回到下一个事件,进行处理,依此类推,直到事件队列为空。
应用程序在整个运行过程中-你在屏幕上点击,下载内容,计时器关闭-该事件循环不断出现,一次处理一次这些事件。

当动作中断时,线程会挂起,等待下一个事件。这个期间它可以触发垃圾收集器,喝个咖啡,等等。
动作中断时:译者的理解队列里没有事件处理,处于空闲状态
Dart用于异步编程的所有高级API和语言功能(期货,流,异步和等待)都基于此简单循环而构建。
例如,假设您有一个启动网络请求的按钮,如下所示:
RaisedButton(
child: Text('Click me'),
onPressed: () {
final myFuture = http.get('https://example.com');
myFuture.then((response) {
if (response.statusCode == 200) {
print('Success!');
}
});
},
)
当您运行应用程序时,Flutter会构建按钮并将其显示在屏幕上。然后您的应用程序等待。
应用的事件循环处于空闲状态,等待下一个事件。在按钮等待点击时,跟按钮不相关的事件可能发生并进入到事件队列被处理。当点击事件发生时,最终会进入队列。
点击事件被取到,等待处理。Flutter 看到这个事件,它的渲染系统说 “事件坐标跟 RaisedButton 匹配”,所以 Flutter 执行 onPressed 函数。这个函数会发起网络请求(返回一个 Future)并使用 then() 方法注册 completion handler。
整个过程就是这样的。事件循环处理完点击事件后将其抛弃。
onPressed 是 RaisedButton 的一个属性,而网络事件为 Future 添加了一个回调,但两者都是在相同的基本操作。它们都是在告诉 Flutter,”你好,一会儿将发生某个事件,你记得执行该事件的代码。”
onPressed 在等待点击,而 Future 在等待网络数据,从 Dart 的视角,这些都是队列中的事件。
这也正是 Dart 中异步代码的工作方式。Future、Steam、以及 async/await,这些 API 都是你告诉 Dart 事件循环执行代码的一种方式。
如果再来回头看刚才的例子,你可以准确地看到它是如何为特定的事件被分解成一小块一小块的。
- 初始的 UI 构建事件
- 点击事件
- 网络响应事件
总结
我们简单地了解了 Dart 中的 Isolate、事件循环以及异步编程基础。
如果你想了解更多,请查看原文的视频。它讨论的是 Future API,这个 API 用于简化异步程序代码。