flutter-isolate详解

一. isolate简介

Dart 是单线程,Dart 为我们提供了 isolate,isolate 跟线程差不多,它可以理解为 Dart 中的线程。isolate 与线程的区别就是线程与线程之间是共享内存的,而 isolate 和 isolate 之间是内存不共享的,所以叫 isolate (隔离)。因此也不存在锁竞争问题,两个Isolate完全是两条独立的执行线,且每个Isolate都有自己的事件循环,它们之间只能通过发送消息通信,所以它的资源开销低于线程。

原文链接:https://blog.csdn.net/u011578734/article/details/108853613
大多数计算机中,甚至在移动平台上,都在使用多核 CPU。为了有效利用多核性能,开发者一般使用共享内存的方式让线程并发地运行。然而,多线程共享数据通常会导致很多潜在的问题,并导致代码运行出错。
为了解决多线程带来的并发问题,Dart 使用 isolates 替代线程,所有的 Dart 代码均运行在一个 isolates 中。每一个 isolates 有它自己的堆内存以确保其状态不被其它 isolates 访问。
每个 isolate 都拥有自己的事件循环及队列(MicroTask 和 Event)。这意味着在一个 isolate 中运行的代码与另外一个 isolate 不存在任何关联。
isolate是Dart对actor并发模式的实现。运行中的Dart程序由一个或多个actor组成,这些actor也就是Dart概念里面的isolate。isolate是有自己的内存和单线程控制的运行实体。isolate本身的意思是“隔离”,因为isolate之间的内存在逻辑上是隔离的。isolate中的代码是按顺序执行的,任何Dart程序的并发都是运行多个isolate的结果。因为Dart没有共享内存的并发,没有竞争的可能性所以不需要锁,也就不用担心死锁的问题。

二. isolate与async关系:

之前介绍过 async/await Future的原理, async关键字实现了异步操作, 而其所谓的异步其实也是运行在同一线程中并没有开启新的线程, 只是通过单线程的任务调度实现一个先执行其他的代码片段,等这边有结果后再返回的异步效果.

  • Isolate可以实现异步并行多个任务
  • Future实现异步串行多个任务
举个栗子:

假设有一个任务,需要计算1+2+...100的和
我们通常会这么写:


class IsolateTestPage extends StatefulWidget {
  @override
  State<StatefulWidget> createState() {
    return IsolateTestPageState();
  }
}

class IsolateTestPageState extends State<IsolateTestPage> {
  var content = "点击计算按钮,开始计算";

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Text("Isolate"),
      ),
      body: SafeArea(
        child: Center(
          child: Column(
            children: <Widget>[
              Container(
                  width: double.infinity, height: 500, child: Text(content)),
              TextButton(
                child: Text('计算'),
                onPressed: () {
                  int result = sum(100);
                  content = "总和$result";
                  setState(() {});
                },
              )
            ],
          ),
        ),
      ),
    );
  }
//计算0到 num 数值的总和
  int sum(int num) {
    int count = 0;
    while (num > 0) {
      count = count + num;
      num--;
    }
    return count;
  }
}

试一下,结果是可以的;但是如果我们改为计算1+2+...100000000000的和,运行代码会发现,直接卡死了
这时候就需要创建一个isolate来执行这个耗时的任务,而不影响其他任务的执行. 那么首先,如何创建一个isolate?

三.创建isolate 及 isolate通信

  • (1).获取当前main isolate的ReceivePort及SendPort
  • (2).使用Isolate.spawn创建新的isolate,需要传入新的isolate需要完成的任务名称及创建者(main isolate)的sendPort. (用于将新的isolate的sendPort传递给创建者)
  • (3).在任务方法中,获取新的isolate的ReceivePort及SendPort
  • (4).将新的isolate的SendPort,通过main isolate的sendPort,发送给main isolate,使新的isolate的SendPort能在main isolate中发送消息
  • (5). SendPort发送消息, ReceivePort接收消息,互相通信

1. receivePort.listen((message) {}) 能收到其对应的sendPort发送的消息

_testIsolate() async {
    ReceivePort rp1 = new ReceivePort();
    SendPort port1 = rp1.sendPort;
    // 通过spawn新建一个isolate,并绑定静态方法
    Isolate newIsolate = await Isolate.spawn(doWork, port1);

    SendPort port2;
    rp1.listen((message) {
      print("rp1 收到消息: $message"); //2.  4.  7.rp1收到消息
      if (message[0] == 0) {
        port2 = message[1]; //得到rp2的发送器port2
      } else {
        if (port2 != null) {
          print("port2 发送消息");
          port2?.send([1, "这条信息是 port2 在main isolate中 发送的"]); // 8.port2发送消息
        }
      }
    });

    print("port1--main isolate发送消息");
    port1.send([1, "这条信息是 port1 在main isolate中 发送的"]); //1.port1发送消息

    // newIsolate.kill();
  }

// 新的isolate中可以处理耗时任务
  static void doWork(SendPort port1) {
    ReceivePort rp2 = new ReceivePort();
    SendPort port2 = rp2.sendPort;
    rp2.listen((message) {
      //9.10 rp2收到消息
      print("rp2 收到消息: $message");
    });
    // 将新isolate中创建的SendPort发送到main isolate中用于通信
    print("port1--new isolate发送消息");
    port1.send([0, port2]); //3.port1发送消息,传递[0,rp2的发送器]
    // 模拟耗时5秒
    sleep(Duration(seconds: 5));
    print("port1--new isolate发送消息");
    port1.send([1, "这条信息是 port1 在new isolate中 发送的"]); //5.port1发送消息
    print("port2--new isolate发送消息");
    port2.send([1, "这条信息是 port2 在new isolate中 发送的"]); //6.port2发送消息
  }

//I/flutter (14639): port1--main isolate发送消息
//I/flutter (14639): rp1 收到消息: [1, 这条信息是 port1 在main isolate中 发送的]
//I/flutter (14639): port1--new isolate发送消息
//I/flutter (14639): rp1 收到消息: [0, SendPort]
//I/flutter (14639): port1--new isolate发送消息
//I/flutter (14639): port2--new isolate发送消息
//I/flutter (14639): rp1 收到消息: [1, 这条信息是 port1 在new isolate中 发送的]
//I/flutter (14639): port2 发送消息
//I/flutter (14639): rp2 收到消息: [1, 这条信息是 port2 在new isolate中 发送的]
//I/flutter (14639): rp2 收到消息: [1, 这条信息是 port2 在main isolate中 发送的]

2. dynamic result = await receivePort.first; 只能收到第一条消息

 _testIsolate() async {
    ReceivePort rp1 = new ReceivePort();
    SendPort port1 = rp1.sendPort;
    // 通过spawn新建一个isolate,并绑定静态方法
    Isolate newIsolate = await Isolate.spawn(doWork, port1);

    SendPort port2;
    dynamic receiveMsg = await rp1.first; //只拿到第一条收到结果
    print('rp1 收到消息--$receiveMsg');
    if (receiveMsg is SendPort) {
      SendPort port2 = receiveMsg;
      // print('rp1 收到消息--port2');
      port2.send([1, "这条信息是 port2 在main isolate中 发送的"]);
    }

    // newIsolate.kill();
  }

// 新的isolate中可以处理耗时任务
  static void doWork(SendPort port1) {
    ReceivePort rp2 = new ReceivePort();
    SendPort port2 = rp2.sendPort;
    rp2.listen((message) {
      print("rp2 收到消息-- $message");
    });
    // 将新isolate中创建的SendPort发送到main isolate中用于通信
    print("port1--new isolate发送消息--port2");
    port1.send(port2);
    // 模拟耗时5秒
    sleep(Duration(seconds: 5));
    print("port1--new isolate发送消息--啊哈哈");
    port1.send("啊哈哈");
  }

3.解决示例问题

知道怎么创建isolate了,我们再看怎么来计算1+2+...100000000000的和

(1)使用listen监听,结果回调的形式

1.创建isolate
2.打通两个isolate的通道(能互相发送消息)
3.main isolate将要计算的最大数传递给new isolate; newisolate计算,计算完成后,将结果发送回 main isolate

calculation(int n, Function(int result) success) async {
    //创建一个ReceivePort
    final receivePort1 = new ReceivePort();
    //创建isolate
    Isolate isolate = await Isolate.spawn(createIsolate, receivePort1.sendPort);
    receivePort1.listen((message) {
      if (message is SendPort) {
        SendPort sendPort2 = message;
        sendPort2.send(n);
      } else {
        print(message);
        success(message);
      }
    });
  }

  //创建isolate必须要的参数
  static void createIsolate(SendPort sendPort1) {
    final receivePort2 = new ReceivePort();
    //绑定
    print("sendPort1发送消息--sendPort2");
    sendPort1.send(receivePort2.sendPort);
    //监听
    receivePort2.listen((message) {
      //获取数据并解析
      print("receivePort2接收到消息--$message");
      if (message is int) {
        num result = summ(message);
        sendPort1.send(result);
      }
    });
  }

  //计算0到 num 数值的总和
  static num summ(int num) {
    int count = 0;
    while (num > 0) {
      count = count + num;
      num--;
    }
    return count;
  }
(2)receivePort.first只能收到第一条消息; 我们可以再创建一个ReceivePort用来传递消息,如下:
static Future<dynamic> calculation(int n) async {
    //创建一个ReceivePort
    final receivePort1 = new ReceivePort();
    //创建isolate
    Isolate isolate = await Isolate.spawn(createIsolate, receivePort1.sendPort);

    //使用 receivePort1.first 获取sendPort1发送来的数据
    final sendPort2 = await receivePort1.first as SendPort;
    print("receivePort1接收到消息--sendPort2");
    //接收消息的ReceivePort
    final answerReceivePort = new ReceivePort();
    print("sendPort2发送消息--[$n,answerSendPort]");
    sendPort2.send([n, answerReceivePort.sendPort]);
    //获得数据并返回
    num result = await answerReceivePort.first;
    print("answerReceivePort接收到消息--计算结果$result");
    return result;
  }

  //创建isolate必须要的参数
  static void createIsolate(SendPort sendPort1) {
    final receivePort2 = new ReceivePort();
    //绑定
    print("sendPort1发送消息--sendPort2");
    sendPort1.send(receivePort2.sendPort);
    //监听
    receivePort2.listen((message) {
      //获取数据并解析
      print("receivePort2接收到消息--$message");
      final n = message[0] as num;
      final send = message[1] as SendPort;
      //返回结果
      num result = summ(n);
      print("answerSendPort发送消息--计算结果$result");
      send.send(result);
    });
  }

  //计算0到 num 数值的总和
  static num summ(int num) {
    int count = 0;
    while (num > 0) {
      count = count + num;
      num--;
    }
    return count;
  }

4. isolate的暂停 恢复 结束

    //恢复 isolate 的使用
    isolate.resume(isolate.pauseCapability);

    //暂停 isolate 的使用
    isolate.pause(isolate.pauseCapability);

    //结束 isolate 的使用
    isolate.kill(priority: Isolate.immediate);

    //赋值为空 便于内存及时回收
    isolate = null;

四.flutter中创建isolate---compute()方法

TextButton(
                child: Text('flutter创建isolate'),
                onPressed: () async {
                  num result = await compute(summ, 10000000000);
                  content = "计算结果$result";
                  setState(() {});
                },
              ),
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
### 回答1: Flutter是Google开源的一款跨平台的UI开发框架,可以快速地构建高质量的移动、Web和桌面应用程序。而Embedded Linux是指Linux操作系统在嵌入式设备中的应用。通过将Flutter与Embedded Linux结合起来,可以让开发者在嵌入式设备上创建漂亮且功能强大的应用程序。 Flutter的跨平台特性使得开发者可以使用相同的代码库在多个平台上运行应用程序,包括嵌入式设备。嵌入式设备通常资源有限,但Flutter的轻量级和高性能使得它非常适合在此类设备上运行。Flutter的热重载功能可以让开发者快速迭代和测试应用程序,提高开发效率。 使用Flutter-Embedded Linux,开发者可以利用Flutter的丰富的UI组件和强大的渲染引擎来创建嵌入式设备上的用户界面。Flutter提供了丰富的UI控件和动画效果,可以实现各种视觉效果和交互体验。Flutter还具备良好的跨平台兼容性和高度定制性,可以适应不同嵌入式设备的各种需求。 除此之外,Flutter-Embedded Linux还提供了与Linux操作系统的良好集成,可以调用底层系统资源和API,如文件系统、网络接口等。这使得开发者可以通过Flutter在嵌入式设备上实现更强大的功能,例如与传感器的交互、与云服务的连接等。 总而言之,Flutter-Embedded Linux是一个强大的开发工具,可以帮助开发者在嵌入式设备中创建高质量的应用程序。它结合了Flutter的跨平台特性和Embedded Linux的优势,为开发者提供了更灵活、高效的开发环境。无论是工业控制、智能家居还是其他嵌入式应用,Flutter-Embedded Linux都能提供良好的开发体验和用户体验。 ### 回答2: Flutter-embedded-linux是指在嵌入式Linux平台上使用Flutter框架进行应用开发的一种技术方案。嵌入式Linux是指在资源有限的嵌入式设备上运行Linux操作系统的系统;而Flutter是一种跨平台的移动应用开发框架,可以同时在Android和iOS上运行。 使用Flutter-embedded-linux可以让开发者在嵌入式Linux平台上开发出跨平台的应用。这样一来,开发者不再需要针对不同的平台编写不同的代码,大大提高了开发效率。同时,Flutter的高性能和优秀的用户体验也被保留在嵌入式设备上。 在使用Flutter-embedded-linux时,开发者需要在嵌入式Linux平台上搭建Flutter的开发环境,包括安装Flutter SDK、配置相关的依赖库等。然后,可以使用Flutter提供的开发工具和API进行应用的开发和调试。 Flutter-embedded-linux可以应用于很多领域,例如智能家居、智能工业设备、嵌入式系统等。开发者可以利用Flutter-embedded-linux开发各种类型的应用,如物联网设备控制应用、工业监控系统、嵌入式音视频播放器等。 需要注意的是,由于嵌入式Linux平台的资源限制,开发者在使用Flutter-embedded-linux时需要特别关注应用的性能和资源消耗情况,避免出现过多的资源占用或性能瓶颈。 总之,Flutter-embedded-linux为开发者在嵌入式Linux平台上开发跨平台应用提供了一种方便、高效、高性能的技术方案,有望在嵌入式设备领域得到广泛应用。 ### 回答3: Flutter-Embedded-Linux是一种使用Flutter框架进行嵌入式开发的技术方案。Flutter是一种跨平台的开源UI框架,可以快速构建高性能、精美的应用程序。而Embedded-Linux则是嵌入式设备常用的操作系统。 通过将Flutter应用程序集成到Linux嵌入式系统中,可以在嵌入式设备上实现高效、流畅和美观的用户界面。Flutter的特点是能够在不同平台上保持一致的用户体验,因此在嵌入式系统上也能够实现类似于移动设备和桌面系统上的应用程序。 使用Flutter-Embedded-Linux进行嵌入式开发有一些优势。首先,Flutter具有快速构建UI界面的能力,可以节省开发时间。其次,Flutter对于动画和渲染效果的支持非常好,可以在嵌入式设备上实现更加流畅和绚丽的动画效果。此外,Flutter还支持热重载功能,可以实时更新应用程序而无需重新启动,极大地提高了开发效率。 然而,使用Flutter-Embedded-Linux也存在一些挑战。嵌入式设备通常资源有限,对占用内存和CPU的要求较高,需要对Flutter应用程序进行优化以提高性能。另外,由于Flutter是基于Dart语言开发的,需要事先熟悉Dart开发语言和Flutter框架的使用。 总之,Flutter-Embedded-Linux是一种用于嵌入式开发的技术方案,可以帮助开发者快速构建高品质的应用程序界面。它在嵌入式设备上的应用可以提供与移动设备和桌面系统相媲美的用户体验。但是,开发者需要注意对资源的合理利用和性能的优化,以确保应用程序在嵌入式设备上能够运行流畅。

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值