我们的flutter应用启动的时候就会开辟一个独立的ioslate,这里面包含了一个独立的内存空间和一个携带 event loops的单一线程和 microTask queue(微任务队列),这个单一线程只处理事件循环。
使用Isolate.spawn()
或Flutter's compute()
函数新建独立的ioslate执行大数据量的计算
不同ioslate之间可以使用ReceivePort相互访问,他们之间唯一的工作方式就是通过不停的消息传递将事件传递给对方,在将事件加入到自己的事件队列中。
_NativeSocket封装了一个操作系统的socket,os是操作系统的意思,也就是说调用socket.nativeCreateUnixDomainConnect方法的时候会到调用操作系统的socket,也就是说网络请求其实是操作系统完成的,这就是为什么flutter应用是单线程模型的应用,但是在默认的isolate做网络请求却不会卡 UI 的原因,因为网络请求就不是dart层完成的,是操作系统完成的
作者:brock
链接:https://www.jianshu.com/p/ac48301db174
Dart 2.15 里新增了 isolate groups 的概念,isolate groups 中的 isolate 共享程序里的各种内部数据结构,也就是虽然 isolate groups 还是不允许 isolate 之间共享可变对象,但 groups 可以通过共享堆来实现结构共享,如:Dart 2.15 后可以将对象直接从一个 isolate 传递到另一 isolate,而在此之前只支持基础数据类型。
在 Flutter 3.7 之前,我们只能从 root isolate 去调用 Platform Channels ,如果你尝试从其他 isolate 去调用 Platform Channels ,就会收获这样的错误警告
在 Flutter 3.7 之前,Platform Channels 是和 _DefaultBinaryMessenger
这个全局对象进行通信,但是一但切换了 isolate ,它就会变为 null ,因为 isolate 之间不共享内存
而从 Flutter 3.7 开始,简单地说,Flutter 会通过新增的 BinaryMessenger 来实现非 root isolate 也可以和 Platform Channels 直接通信,例如:我们可以在全新的 isolate 里,通过 Platform Channels 获取到平台上的原始图片后,在这个独立的 isolate 进行一些数据处理,然后再把数据返回给 root isolate ,这样数据处理逻辑既可以实现跨平台通用,又不会卡顿 root isolate 的运行。
将 Future.wait
的 await
修改为 .then
去执行,如果这时候你再调用 spawn
和 compute
,你就会发现 spawn
下代码依然可以正常执行,但是 compute
却不再正常执行。
compute
不就是 Flutter 针对 Isolate.spawn
的简易封装吗?
其实原因就在这个封装上,compute
现在不是直接执行 Isolate.spawn
代码,而是执行 Isolate.run
,而 Isolate.run
针对 Isolate.spawn
做了一些特殊封装。
compute
内部会将执行对象封装成 _RemoteRunner
再交给 Isolate.spawn
执行,而 _RemoteRunner
在执行时,会在最后强制调用 Isolate.exit
,这就会导致前面的 Future.wait
还没执行,而 Isolate
就退出了,从而导致代码无效的原因。
Flutter 小技巧之 3.7 性能优化background isolate - 知乎
简单示例:
import ‘package:flutter/services.dart’; import ‘package:shared_preferences/shared_preferences.dart’;void main() { // Identify the root isolate to pass to the background isolate. // (API introduced in Flutter 3.7) RootIsolateToken rootIsolateToken = RootIsolateToken.instance!; Isolate.spawn(_isolateMain, rootIsolateToken); }void _isolateMain(RootIsolateToken rootIsolateToken) async { // Register the background isolate with the root isolate. BackgroundIsolateBinaryMessenger .ensureInitialized(rootIsolateToken); // You can now use the shared_preferences plugin. SharedPreferences sharedPreferences = await SharedPreferences.getInstance(); print(sharedPreferences.getBool(‘isDebug’)); }
https://medium.com/flutter/introducing-background-isolate-channels-7a299609cad8