Dart是一种单线程语言,但是后来也提供了 futures、 streams 等后台工作的支持。 本文讲述的是Dart后台工作的基础:隔离(isolates )和事件循环(event loops)。 isolates isolates 是所有Dart代码运行的地方。它就像机器上的一个小空间,有自己的私有内存块和一个运行事件循环的线程。 在许多其他语言(如C++)中,可以让多个线程共享同一内存,并运行想要的任何代码。 在Dart中,每个线程都有自己的隔离区和自己的内存,线程只处理事件。 许多Dart应用程序在一个隔离(isolate)中运行所有代码,但如果需要是可以有多个 isolate。 比如要执行的计算量太大,如果它在主隔离中运行,可能会导致丢帧,所以可以使用isolate.spawn()或Flutter的compute()函数。这两个函数都创建了一个单独的 isolate 来进行数字运算,让主 isolate 可以自由地重建和渲染小部件树。
新 isolate 区有自己的事件循环和内存,而原始 isolate ,即使它是这个新隔离区的父隔离区——也不允许访问这些内存。
这就是 isolate 这个名字的来源:这些小空间彼此隔离。 事件循环 事实上,isolate 是可以协同工作,依赖与 isolate 之间的消息传递。一个isolate 向另一个 isolate 发送消息,接收 isolate 使用其事件循环处理该消息。 如果你有Java或C++这样的语主基础,可能会理解的快一点:共享内存的缺乏。 isolate 中的内存分配和垃圾收集不需要锁定。只有一个线程,所以如果它不忙,这对Flutter应用程序来说效果很好,它们有时需要快速构建和删除一堆小部件。 想象一下:一个应用程序在时间线上的生命。应用程序启动,应用程序停止,其间发生了一系列事件——磁盘的I/O、用户的手指敲击……各种各样的事情。 应用程序无法预测这些事件何时发生或以何种顺序发生,它必须用一个从不阻塞的线程来处理所有这些事件。 因此,该应用程序运行一个事件循环。它从事件队列中获取最旧的事件,对其进行处理,返回下一个事件,处理它,依此类推,直到事件队列为空。 在应用程序运行的整个过程中——你在屏幕上点击,下载东西,计时器关闭——事件循环不断,一次处理一个事件。 当操作中断时,线程就会挂起,等待下一个事件。 Dart为异步编程提供的所有高级API和语言功能——futures、streams、异步(async)和等待(await)——都是围绕这个简单的循环构建的。 如下是一个启动网络请求的按钮:
当你运行你的应用程序时,Flutter会构建按钮并将其放在屏幕上。然后你的应用程序会等待。 你的应用程序的事件循环只是有点空闲,等待下一个事件。与按钮无关的事件可能会进入并得到处理,而按钮则坐在那里等待用户点击。最终,点击事件进入队列。 在上述网络请求的代码中,网络事件使用到了一个 Future 事件,与按钮的 onPressed 事件,它们都是在告诉 Flutter 稍后可能会看到一个特定的类型事件出现。从Dart的角度来看,这两者都是队列中的事件。 |
|