分享

Flutter隔离(isolates )和事件循环(event loops)

 程序员读书空间 2023-11-07 发布于浙江

Dart是一种单线程语言,但是后来也提供了 futures、 streams 等后台工作的支持。

本文讲述的是Dart后台工作的基础:隔离(isolates )和事件循环(event loops)。

isolates 

isolates 是所有Dart代码运行的地方。它就像机器上的一个小空间,有自己的私有内存块和一个运行事件循环的线程。

在许多其他语言(如C++)中,可以让多个线程共享同一内存,并运行想要的任何代码。

在Dart中,每个线程都有自己的隔离区和自己的内存,线程只处理事件。

许多Dart应用程序在一个隔离(isolate)中运行所有代码,但如果需要是可以有多个 isolate。

比如要执行的计算量太大,如果它在主隔离中运行,可能会导致丢帧,所以可以使用isolate.spawn()或Flutter的compute()函数。这两个函数都创建了一个单独的 isolate 来进行数字运算,让主 isolate 可以自由地重建和渲染小部件树。

import 'dart:isolate';    void main() {    // 创建一个新的Isolate    var isolate = Isolate.spawn(doSomeWork);        // 在主线程中等待新Isolate的完成    isolate.send(new Completer<void>.complete());        // 当新Isolate完成任务时,Completer会完成,这个if语句就会执行    if (Completer.allComplete(null)) {      print('新Isolate完成任务了');    } else {      print('新Isolate没有完成任务');    }  }    void doSomeWork() {    // 这个方法会在新的Isolate中运行    for (int i = 0; i < 10000; i++) {      // 一些CPU密集型操作...    }        // 当这个方法完成时,它会发送一个完成消息到主Isolate    send(new Completer<void>.complete());  }

新 isolate 区有自己的事件循环和内存,而原始 isolate ,即使它是这个新隔离区的父隔离区——也不允许访问这些内存。

import 'dart:isolate';    void main() {    // 创建一个新的Isolate上下文    var context = new Isolate.Context();      // 在新的Isolate上下文中执行计算密集型任务    var result = compute(doSomeWork, context);      // 处理计算结果    print('计算结果: $result');  }    dynamic doSomeWork() {    // 一些计算密集型操作...    return 42; // 返回计算结果  }

这就是 isolate 这个名字的来源:这些小空间彼此隔离。

事件循环

事实上,isolate 是可以协同工作,依赖与 isolate 之间的消息传递。一个isolate 向另一个 isolate 发送消息,接收 isolate 使用其事件循环处理该消息。

如果你有Java或C++这样的语主基础,可能会理解的快一点:共享内存的缺乏。

isolate  中的内存分配和垃圾收集不需要锁定。只有一个线程,所以如果它不忙,这对Flutter应用程序来说效果很好,它们有时需要快速构建和删除一堆小部件。

想象一下:一个应用程序在时间线上的生命。应用程序启动,应用程序停止,其间发生了一系列事件——磁盘的I/O、用户的手指敲击……各种各样的事情。

应用程序无法预测这些事件何时发生或以何种顺序发生,它必须用一个从不阻塞的线程来处理所有这些事件。

因此,该应用程序运行一个事件循环。它从事件队列中获取最旧的事件,对其进行处理,返回下一个事件,处理它,依此类推,直到事件队列为空。

在应用程序运行的整个过程中——你在屏幕上点击,下载东西,计时器关闭——事件循环不断,一次处理一个事件。

当操作中断时,线程就会挂起,等待下一个事件。

Dart为异步编程提供的所有高级API和语言功能——futures、streams、异步(async)和等待(await)——都是围绕这个简单的循环构建的。

如下是一个启动网络请求的按钮:

TextButton(  child: Text('点击测试'),  onPressed: () {final myFuture = http.get('https://');    myFuture.then((response) {if (response.statusCode == 200) {print('Success!');      }    });  },)

当你运行你的应用程序时,Flutter会构建按钮并将其放在屏幕上。然后你的应用程序会等待。

你的应用程序的事件循环只是有点空闲,等待下一个事件。与按钮无关的事件可能会进入并得到处理,而按钮则坐在那里等待用户点击。最终,点击事件进入队列。

在上述网络请求的代码中,网络事件使用到了一个 Future 事件,与按钮的 onPressed 事件,它们都是在告诉 Flutter 稍后可能会看到一个特定的类型事件出现。从Dart的角度来看,这两者都是队列中的事件。

    转藏 分享 献花(0

    0条评论

    发表

    请遵守用户 评论公约

    类似文章 更多