浅谈 Flutter 的并发和 isolates

有没有一种感觉,就我自己而言,Flutter 项目开发了好几个了,但是对这个 isolates 印象依旧很陌生,日常开发中好像很少见到它身影或者用到它,但真实情况是这样的吗?今天就来聊一聊它。

Flutter 中的 isolates 是什么?

Flutter 中,Isolates(隔离区)是一种轻量级的并发执行单元,用于在单个进程中执行代码。与线程有点儿像,但是每个 Isolates 之间又是完全独立的,彼此之间没有共享内存。每个 Isolates 都有自己的内存堆,可以独立执行代码,处理任务,而不会受到其他 Isolates 的影响。它们之间只能通过消息传递进行通信。

我们可以通过 Isolate.current 来查看当前正在执行的 Isolate

正在执行的 Isolate

Flutter 中有哪些 isolates

Flutter 中,主要有两种类型的 Isolates

  • Main Isolates: 也称为 UI 线程或 UI Isolate,启动应用程序时,Dart VM 会自动创建一个 Isolate 实例并在其上运行您的“主”代码,相当于是 Flutter 应用程序的主线程,负责处理用户界面和用户交互。在 Main Isolate 中执行的代码通常包括构建 UI、处理用户输入等任务。打印 Isolate.current.debugName 可以看到:
Main Isolates
  • Background Isolates:运行在后台,可以用于执行耗时操作,如网络请求、长的JSON 解析、文件读取、计算密集型任务等。通过后台 Background Isolates,可以避免在主 Isolate 中执行长时间运行的任务,从而保持应用程序的响应性。

默认情况下,Flutter 应用程序会在 Main Isolates 上完成所有工作,切处理速度很快,不会出现 UI 卡顿,但执行异常大的计算的时候,会出现 UI 卡顿,和原生开发一样,在子线程执行耗时操作,在 Flutter 中就需要将耗时操作放在辅助的 Isolates 中,也就是 Background Isolates

事件循环与页面卡顿

每个 Isolates 都有自己的内存和事件循环,事件循环是按照事件添加到事件队列的顺序来处理事件。在 Main Isolates 中,这些事件可以是用户的点击事件、函数执行和绘制视图到屏幕上等等。 为了更平滑的渲染视图,Flutter 底层会以 60次/每秒 向事件队列添加“绘制帧”事件(对于 60Hz 设备)。 如果这些事件没有及时处理,就会出现 UI 卡顿或者没有响应。

事件循环与页面卡顿

如果某个事件无法在两帧之间的时间(帧间隙)内完成时,最好将这个事件的执行放在其它的 Isolates,用来确保 Main Isolates 每秒可以生成 60 帧。

Isolates 之间通信

创建一个新的 isolate 有两种方式,构造方法 Isolate(...) 和 静态方法 Isolate.spaw。下面例子创建一个新的 isolate 每隔一秒向 Main Isolates 发送当前时间戳。

Future<void> main() async {
  if (kDebugMode) {
    print("Isolate.current = ${Isolate.current.debugName}");
  }

  Isolate timerIsolate;
  final mainControlPort = ReceivePort()..listen((message) {
    print("sending back to MainIsolate: $message");
  });

  timerIsolate = await Isolate.spawn(
    timerTick,
    mainControlPort.sendPort,
    debugName: "TimerIsolate",
  );

  runApp(App());
}

void timerTick(SendPort mainPort) async {
  print("${Isolate.current.debugName} started");
  Timer.periodic(const Duration(seconds: 1), (timer) {
    final ts = DateTime.now().toIso8601String();
    mainPort.send(ts);
  });
}

执行结果的 log

Performing hot restart...
Syncing files to device iphone...
Restarted application in 886ms.
flutter: Isolate.current = main
flutter: TimerIsolate started
flutter: sending back to MainIsolate: 2024-03-29T16:49:39.598746
flutter: sending back to MainIsolate: 2024-03-29T16:49:40.594376
flutter: sending back to MainIsolate: 2024-03-29T16:49:41.594763
flutter: sending back to MainIsolate: 2024-03-29T16:49:42.594927
flutter: sending back to MainIsolate: 2024-03-29T16:49:43.593959
flutter: sending back to MainIsolate: 2024-03-29T16:49:44.594098
flutter: sending back to MainIsolate: 2024-03-29T16:49:45.594441
flutter: sending back to MainIsolate: 2024-03-29T16:49:46.594051
flutter: sending back to MainIsolate: 2024-03-29T16:49:47.594242
Application finished.
Isolates 之间的通信

实际上,FlutterIsolates 就是 Actor model 实现,Isolates 之间只能通过消息传递来相互通信,而且消息是通过复制的方式从发送 Isolate 传递到接收的 Isolate,也就是说,当这个数据消息在接收的 Isolate 上发生变化的时候,发送 Isolate 的原数据不受影响。

SendPort.send: 发送时生成可变消息的副本

传递的消息是不可变对象时 immutable objects,如不可变的字符串,会发送对该对象的引用,而不是复制的对象,这样做也是为了获得更好的性能。不可变对象无法更新,也符合Actor model 的实现。

Isolate.exit:发送对消息的引用

特殊情况就是当发送方Isolate 在发送完消息后就销毁了,会将消息的所有权传递给接收的 Isolate,以确保只有一个 Isolate 可以访问该消息。

根据这些特性,所以我们在使用 Isolate 要注意这一点,当你在 Isolates 传递一个全局可变变量时,该全局变量会在其它 Isolate 复制一份,而在主隔离中却保持不变。

还有一点,目前 Web 平台还不支持 Isolate

本篇文章就到这里,感谢您的阅读!

©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 220,809评论 6 513
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 94,189评论 3 395
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 167,290评论 0 359
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 59,399评论 1 294
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 68,425评论 6 397
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 52,116评论 1 308
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 40,710评论 3 420
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 39,629评论 0 276
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 46,155评论 1 319
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 38,261评论 3 339
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 40,399评论 1 352
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 36,068评论 5 347
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 41,758评论 3 332
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 32,252评论 0 23
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 33,381评论 1 271
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 48,747评论 3 375
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 45,402评论 2 358

推荐阅读更多精彩内容