5分钟了解Flutter线程Isolate的运用以及Isolate到底是怎样执行的

Isolate在dart是什么

Isolate中文的意思是“隔离”。用宏观角度来看,在dart使用Isolate,相当于使用线程。
我们来看看官方给出的解析:

"所有 Dart 代码都在isolate中运行,isolate与线程类似,但不同之处在于isolate有自己的isolate内存。 它们不以任何方式共享状态,只能通过消息传递进行通信。 默认情况下,Flutter 应用程序在单个isolate区(主isolate区)上完成所有工作。 在大多数情况
但有时,应用程序需要执行异常大的计算,这可能会导致“UI jank”(不稳定的运动)。 如果您的应用程序因此而遇到卡顿,您可以将这些计算移至辅助isolate中。 这允许底层运行时环境与主 UI isolate的工作同时运行计算,并利用多核设备。
每个isolate区都有自己的内存和事件循环。 事件循环按照事件添加到事件队列的顺序处理事件。 在主isolate区上,这些事件可以是任何事件,从处理用户在 UI 中点击、执行功能到在屏幕上绘制框架。 "

flutter线程内存隔离

我们从下面这张官方给出的图,可以发现Dart虚拟机与Android虚拟机截然不同的是,运行中的Isolate是内存独立的。
在这里插入图片描述
显而易见,Isolate的最大优势就是创建线程不需要对内存加锁,创建速度快,。并且垃圾回收不需要暂停其他业务线程,可以隔绝其他业务线程带来的内存抖动的影响,从而优化业务了帧率(不熟悉内存抖动,可以看看这篇文章<<Android内存抖动>>)。但是缺点也明显,内存不共享,通讯需要拷贝内容

Isolate的使用

第一种,无参数

使用Isolate.run

String runData = await Isolate.run(<String>() {
  return 'run ,run run';
});
print("Isolate.run:$runData");

运行结果:

Isolate.run:run ,run run

第二种,有参数

可以使用函数compute, 也可以使用Isolate.spawn

使用compute:

class Data {
  String value = 'data';
}

  String computeData = await compute((message) {
   print("compute>>:${message.value}");
   return 'kakakak';
 }, Data()..value = 'compute,compute');
 print("compute.run:$computeData");

运行结果:

Shell: compute>>:compute,compute
compute.run:kakakak

使用Isolate.spawn

 await Isolate.spawn((message) {
   print('Isolate.spawn:${message.value}');
 }, Data());

运行结果:

Shell: Isolate.spawn:data

Isolate与外面线程通讯

RawReceivePort相当于接收器,里面有个订阅回调,接收Isolate返回的数据

 final receivePort = RawReceivePort();
 receivePort.handler = (data) {
   print(data);
   if (data == 'close') {
     receivePort.close();
   }
 };
 Isolate.spawn((port) {
   var i = 0;
   while (i < 5) {
     port.send('create:${i++}');
   }
   port.send('close');
 }, receivePort.sendPort);

运行结果:

Shell: create:0
Shell: create:1
Shell: create:2
Shell: create:3
Shell: create:4
Shell: close

Isolate以文件形式加载到内存运行

提供个dart文件,然后使用Isolate.spawnUri这个方法加载这个文件执行。但是入口必须是如下

void main(List<String> args,SendPort sendPort){

}

下面提供完整的例子:
编写一个dart文件,名字可以任意取,这里叫做isloate_test.dart

import 'dart:convert';
import 'dart:isolate';

void main(List<String> args,SendPort sendPort){
  print(jsonEncode(args));
}


然后在其他dart文件加载

  ReceivePort receiveUriPort = ReceivePort();
 await Isolate.spawnUri(
    Uri(path: './isloate_test.dart'), ['a', 'b', 'c'], receiveUriPort.sendPort);

运行结果:

[‘a’, ‘b’, ‘c’]

Isolate运用场景

由于UI代码是在UI线程里面执行的,为了避免影响UI线程的运算,非UI的业务都建议使用其他线程来进行执行,以优化UI的流畅度
在这里插入图片描述

Isolate到底是不是真的线程

微观角度来看,Isolate真不是具体的线程,它只是dart运输到线程执行的一种包装载体。并且是放到系统的线程池里面执行的一种包装。
在这里插入图片描述
Isolate是由Dart VM Thread从系统里面进行创建来调度管理的。 Isolate类似Java的Runnable

如何证明Isolate不是真的线程?

很简单,你只需要跑到 点击>>isolate.cc<<的源码里面阅读一下就可以知道它是交给tread_pool线程池执行的。

//...
isolate->group()->thread_pool()->Run<SpawnIsolateTask>(isolate,
                                                         std::move(state));
//...

是不是很赞?如果这篇文章对你有帮助,请关注🙏,点赞👍,收藏😋三连哦

  • 19
    点赞
  • 18
    收藏
    觉得还不错? 一键收藏
  • 2
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值