Flutter随笔

Isolate.dart阅读

2020-09-22  本文已影响0人  嘛尼嘛哄

Isolate

方法介绍

class Isolate {
 //ping和kill的参数,常量标志位,代表立即执行
  static const int immediate = 0;
//ping和kill命令的参数,代表在一下一次事件之前执行
  static const int beforeNextEvent = 1;

//控制端口,用来发送控制类型的消息给isolate,举个不恰当的栗子,它是一个插头,isolate就像是插座,他们之间有着一一对应的关系,电流好比消息,这样应该比较容易理解了把,给插座充电(发送消息给isolate)
 
//一些特定类型的消息需要isolate的支持,比如发送暂停或者终止能力,就比如充电,电流太小或这太大,插座可能不支持,太小无法提供能量,太大会烧坏。这里其实指的是 controlport发送的消息 isolate处理不了,无法接收,消息就被无视了。
 
    //通过非空判定,以及它和controlport关联的是否为当前对应的isolate来决定controlport是否可以发送暂停消息给isolate
  final Capability pauseCapability;

  //通过非空判定,以及它和controlport关联的是否为当前对应的isolate来决定controlport是否可以发送终止消息给isolate
  final Capability terminateCapability;
 
//设置debug name便于调试,它在转换为c embedding API的时候会被mapping成 Dart_DebugName.
  external String get debugName;

 //创建一个受限制的`Isolate`,它有2个capability,如果不传将失去这个能力
  Isolate(this.controlPort, {this.pauseCapability, this.terminateCapability});

  //获取当前正在使用的Isolate
  external static Isolate get current;

  //Ioslate执行的包路径,如果没有设置它将返回为null
  external static Future<Uri> get packageConfig;

  // 创建一个新的Isolate, entry-point 是当前Isolate的参数,它是一个函数指针, 初始化之后 entrypoint函数将会首先在新建的Isolate内部调用,并message作为它的参数
 //这个方法必须在最高层级或
 //通常初始化的 message会包含一个SendPort,这样就能和外部的传入message的Isolate双向通信了。  
 //paused代表了当前isolate的创建之后的初始化状态,如果需要发送消息,确保它不是暂停状态
  external static Future<Isolate> spawn<T>(
      void entryPoint(T message), T message,
      {bool paused: false,
      bool errorsAreFatal,
      SendPort onExit,
      SendPort onError,
      @Since("2.3") String debugName});

 //从指定的package中初始化一个Isolate, 并调用它的main函数,同时监听它的错误回调
  external static Future<Isolate> spawnUri(
      Uri uri,
      List<String> args,
      var message,
      {bool paused: false,
      SendPort onExit,
      SendPort onError,
      bool errorsAreFatal,
      bool checked,
      Map<String, String> environment,
      @Deprecated('The packages/ dir is not supported in Dart 2')
          Uri packageRoot,
      Uri packageConfig,
      bool automaticPackageResolution: false,
      @Since("2.3")
          String debugName});

   //暂停/恢复
  Capability pause([Capability resumeCapability]) { ..
  external void _pause(Capability resumeCapability);
  external void resume(Capability resumeCapability);

 //拦截退出事件,获取取完消息再退出
  external void addOnExitListener(SendPort responsePort, {Object response});
 // 释放上面的钩子
  external void removeOnExitListener(SendPort responsePort);
 
//设置位置的异常是否需要终止调当前的isolate,这个调用依赖于`terminateCapability`,
//由于isolate并行运行,很有可能出错, 建议使用正确的方式来初始化isolte,设置暂停后再执行改方法,然后再开启isolate
  external void setErrorsFatal(bool errorsAreFatal);

  //是否要在事件执行完之前杀调isolate
  external void kill({int priority: beforeNextEvent});

   //请求isolate的 response数据 
// priority: immediate/ beforeNextEvent
  external void ping(SendPort responsePort,
      {Object response, int priority: immediate});
 
  external void removeErrorListener(SendPort port);
  
//从当前的isolate定义一个广播流通知
  Stream get errors {
    StreamController controller;
    RawReceivePort port;
    void handleError(message) {
      List listMessage = message;
      String errorDescription = listMessage[0];
      String stackDescription = listMessage[1];
      var error = new RemoteError(errorDescription, stackDescription);
      controller.addError(error, error.stackTrace);
    }

    controller = new StreamController.broadcast(
        sync: true,
        onListen: () {
          port = new RawReceivePort(handleError);
          this.addErrorListener(port.sendPort);
        },
        onCancel: () {
          this.removeErrorListener(port.sendPort);
          port.close();
          port = null;
        });
    return controller.stream;
  }
}

基本用法

  1. 一次性链接,处理单一的操作

void isolateTest1() async {
  ReceivePort receivePort = ReceivePort();
  
  //创建一个isoLater  **The entry-point function is invoked in the new isolate with [message] as the only argument.**
  await Isolate.spawn(entryPoint, receivePort.sendPort);
   //
  receivePort.listen((data) {
    print("receivePort: ${Isolate.current.hashCode}");
    if (data is SendPort) {
      data.send('receivePort hello!');
    } else {
      print('current isolate: $data');
    }
  });
}
//entryPoint是一个函数指针,在新的Ioslate创建之后首先执行它,所以它的堆栈空间肯在新创建的isolate上面
void entryPoint(SendPort sendPort) {
  ReceivePort r = ReceivePort();
  sendPort.send(r.sendPort);
  print("entryPoint: ${Isolate.current.hashCode}");
  r.listen((data) {
    print('new isolate: $data');
    sendPort.send('entryPoint hello!');
  });
}

输入出日志如下:

main isolate: 174209548
entryPoint: 1004649793
receivePort: 174209548
new isolate: receivePort hello!
receivePort: 174209548
current isolate: entryPoint hello!
  1. 两个Isolate实时链接
void main() async {
  await isolateTest1();
}

//创建一个Isolate进行双向通信
void isolateTest1() async {
  ReceivePort messageRecievedPort = ReceivePort();
  RawReceivePort onExitRecievedPort = RawReceivePort((exitData) {
    print('${Isolate.current.debugName} onExitRecievedPort $exitData ');
  });

  RawReceivePort onErrorRecievedPort = RawReceivePort((errorData) {
    print('${Isolate.current.debugName} onErrorRecievedPort $errorData ');
  });

  //创建一个isoLater  **The entry-point function is invoked in the new isolate with [message] as the only argument.**
  //根据flutter framework的描述,`entryPoint`
  /**
   * @param1:  `Future<Isolate>` 返回一个新的Isolate对象
   * @param2:  `void Function(T) entryPoint`, 新的Isolate的入口函数,Isolate创建完成后会首先执行此方法
   * @param3: 用于传递给新的Isolate的数据,作`void Function(T) entryPoint`的参数
   * @param4: `bool paused = false`初始化创建Isolate是否先将其暂停
   * @param5: `bool errorsAreFatal = true`,指定Isolate的错误判定行为
   * @param6: `SendPort onExit` sendport退出时的回调
   * @param7: `SendPort onError`错误时的回调
   * @param8: `Isolate`的名字
   * entryPoint 
   * Future<Isolate> spawn<T>(void Function(T) entryPoint, T message, {bool paused = false, bool errorsAreFatal = true, SendPort onExit, SendPort onError, String debugName})
  */

  await Isolate.spawn(
    entryPoint,
    messageRecievedPort.sendPort,
    onExit: onExitRecievedPort.sendPort,
    onError: onErrorRecievedPort.sendPort,
    debugName: 'malimahong',
  );

  print('1. current Isolate: ${Isolate.current.debugName} call spawn method create new Isolate');
  SendPort sendPort;
  messageRecievedPort.listen((data) async {
    if (data is SendPort) {
      sendPort = data;
      print('3. current Isolate: ${Isolate.current.debugName} recieved 🤝');
      print('4. current Isolate: ${Isolate.current.debugName} send agree 🤝');
      sendPort.send('agree 🤝');
    } else { 
      await Future.delayed(Duration(seconds:1));
      print('${Isolate.current.debugName} send $data -');

      sendPort.send('data -'); 
    }
  });
}

执行流行如下,可以类比成TCP的握手行为,在初始化分配新的Isolate空间后,它首先找到自己的入口函数entryPoint,入口函数包含了上一个Isolate带来的参数,如果这个参数只是简单的消息,那么只能接收消息,无法实时通信,所以这个参数必须是一个函数指针

  1. current Isolate: main call spawn method create new Isolate.
  2. new Isolate malimahong pass sendPort to main ,say hello, start 🤝
  3. current Isolate: main recieved 🤝
  4. current Isolate: main send agree 🤝
  5. current Isolate: malimahong reieved agree 🤝 complete 🤝
    malimahong send +
    main send send + -
    malimahong send data - +

flutter engine部分待续

上一篇 下一篇

猜你喜欢

热点阅读