- 它是一个独立的dart执行上下文,有自己独立的空间,不能被其他的isolate直接访问,只能访问内部的资源,
- 其它isolate如果需要访问,只能通过对应的端口访问
- 当通过spawning方法生成一个新的isolate,调用spawning方法的isolate将会获得一个新的isolate如果创建成功
- isolate有自己独立的空间,单独运行这自己的event loop,和主isolate一样有自己独立的taskqueue.
方法介绍
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;
}
}
基本用法
-
单次任务,2个Isolate 只交互处理一次,任务就完成了
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!
-
持续任务,2个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 -');
}
});
}
工作流程
- 执行流行如下:
- current Isolate: main call spawn method create new Isolate.
- new Isolate malimahong pass sendPort to main ,say hello, start ????
- current Isolate: main recieved ????
- current Isolate: main send agree ????
- current Isolate: malimahong reieved
agree ???? complete ????
malimahong send +
main send send + -
malimahong send data - +
可以类比成简单的握手行为,在初始化分配新的Isolate空间后,它首先找到自己的入口函数entryPoint ,入口函数包含了上一个Isolate带来的参数,如果这个参数只是简单的消息,那么只能接收消息,无法实时通信,所以这个参数必须是一个函数指针.
根据输出日志顺序可以知道在新的isolate初次创建时,首先会调用第一个参数void entryPoint(T message) ,所以这个方法的实现部分函数的堆栈信息都在新建的Isolate中.除此以外的部分就是另一个isolate. 通过指定各自的receivePort然后就能快的和外成isolate通信了.
|
请发表评论