图解Flutter创建Isolate的过程及通信

Flutter的代码都是默认跑在root isolate上的,负责渲染,还有UI交互。 使用场景:有耗时的任务,好比读写文件、密集型计算等,须要新建一个isolate来处理,看上去相似js的Web Workerjson

如何建立一个isolate呢?

先看下示意图,总共须要4步来作:markdown

  1. 第一步及第二步是创建相似握手的一个过程
  2. 第三步和第四步是发送数据及处理数据并返回的过程

具体示例代码

看代码前先了解几个关键类:app

  1. 使用SendPort是isolate之间的惟一通信方式,能够发送任何信息。
  2. ReceivePort 是一个非广播流,只能有一个监听者,监听后才能够收到message

对应的测试代码:async

loadData() async {
    // 经过spawn新建一个Isolate,绑定静态方法并传递App端port1
    print('spawn1');
    ReceivePort receivePort = ReceivePort();//App端的监听
    await Isolate.spawn(dataLoader, receivePort.sendPort`);//spawn(port1)
    print('spawn2');

    // 获取新Isolate端的port2
    SendPort sendPort = await receivePort.first;
    print('spawn3');
    //把要作的任务 使用Isolate端的port2 传递过去
    List dataList = await sendReceive(sendPort, 'https://jsonplaceholder.typicode.com/posts');//要作的具体任务,封装成Future方法
    print('spawn4');
    print('dataList $dataList');
  }

  // Isolate端的处理方法
  static dataLoader(SendPort sendPort) async {
    // 建立监听port2,并经过app端port1,回传Isolate端的port2
    ReceivePort receivePort = ReceivePort();//Isolate端的监听
    print('Loader1');
    sendPort.send(receivePort.sendPort);// port1.send(port2);
    print('Loader2');
    // 监听全部App端发来的消息,并进行处理,能够传key,参数,作区分处理等等
    await for (var msg in receivePort) {
      String requestURL = msg[0];
      SendPort callbackPort = msg[1];// port3
      print(requestURL);
      print('Loader3');

     /// 假设处理任务
      final dataList = await Future.delayed(Duration(seconds: 5), () {
        return ['sdf', 'ggg'];
      });
      print('Loader4');
      // 回调返回值给调用者
      callbackPort.send(dataList);
      print('Loader5');
    }
  }

  /// 建立本身的监听port,而且向新isolate发送消息
  ///
  /// 为何要建立port3呢?
  ///
  /// 由于ReceivePort是Stream,只能监听一次,为了更好的隔离任务监听,因此就新建了个,
  /// 并且尽可能每一个任务都本身写一个监听,彼此互不影响
  Future sendReceive(SendPort sendPort, String url) {
    // 任务监听器
    ReceivePort receivePort = ReceivePort();
    print('send1');
    // 发送要作的事情
    sendPort.send([url, receivePort.sendPort]);//port2.send(tohandletask, port3);
    print('send2');
    // 接收到返回值,返回给调用者
    return receivePort.first;
  }
复制代码

上面代码对应的日志以下:post

flutter: spawn1 flutter: Loader1 flutter: Loader2 flutter: spawn2 flutter: spawn3 flutter: send1 flutter: send2 flutter: https://jsonplaceholder.typicode.com/posts flutter: Loader3 flutter: Loader4 flutter: Loader5 flutter: spawn4 flutter: dataList [sdf, ggg] 复制代码

若有问题欢迎指正~~测试

相关文章
相关标签/搜索