Isolate学习
模仿computer的使用方式,使用isolate封装出一个工具。
基本概念
- 每个isolate之间都是相互隔离的,无法共享内存,所以他们之间的通信唯一方式只能是通过Port进行,
实现流程
- 在主isolate创建一个子isolate,将receivePort的sendPort传递个子isolate(packageTask为子isolate的入口函数)
// 创建管道
ReceivePort receivePort = ReceivePort();
// 创建新的Isolate
Isolate isolate = await Isolate.spawn<SendPort>(packageTask, receivePort.sendPort);
- 在子isolate中创建另一个receivePort2,将receivePort2的sendPort通过receivePort.sendPort发送给主isolate
void packageTask(SendPort sendPort) {
ReceivePort receivePort2 = ReceivePort();
SendPort sendPort2 = receivePort2.sendPort;
receivePort2.listen((data) {
/// 监听回调,拿到主isolate的耗时操作并执行
Function callback = data['callback'];
/// 将执行完的结果再发送给主isolate
sendPort.send(callback(data['message']));
});
/// 第2步:将receivePort2.sendPort发送个主isolate
sendPort.send({WXIsolatePortKey: sendPort2});
}
- 在主isolate的监听回调中拿到receivePort2的sendport, 然后将需要执行的耗时操作函数及参数通过receivePort2的sendport发送个子Isolate
/// 监听管道消息
receivePort.listen((data) {
if (data is Map<String, dynamic> && data.containsKey(WXIsolatePortKey)) {
/// 第3步: 拿到receivePort2.sendPort
sendPort2 = data[WXIsolatePortKey];
/// 将参数及耗时任务通过sendPort2发送给子isolate
Map<String, dynamic> param = {'message': arguments, 'callback': callback};
sendPort2.send(param);
} else {
/// 这边收到最终执行完的结果
result.complete(data);
/// 拿到结果后关闭
closeIsolate(isolate, receivePort);
}
}, onError: (error) {
closeIsolate(isolate, receivePort);
});
- 子isolate通过receivePort2的回调监听拿到函数及参数并调用,将函数执行的结果通过receivePort的sendPort返回给主isolate,这样就实现了耗时任务的并发进行
receivePort2.listen((data) {
/// 第4步:
/// 监听回调,拿到主isolate的耗时操作并执行
Function callback = data['callback'];
/// 将执行完的结果再发送给主isolate
sendPort.send(callback(data['message']));
});
完整代码
- 调用方式
import 'wx_isolate.dart';
import 'package:flutter/foundation.dart';
import 'package:flutter/material.dart';
class FirstPage extends StatefulWidget {
@override
_FirstPageState createState() => _FirstPageState();
}
class _FirstPageState extends State<FirstPage> {
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(title: Text('title')),
body: Center(
child: FutureBuilder(
// future: getDataByCompute(),
future: getDataByIsolate(),
builder: (ctx, snap) {
if (snap.hasData) {
return Text(snap.data.toString());
}
return CircularProgressIndicator();
},
),
),
);
}
/// isolate 测试
Future<String> getDataByIsolate() async {
String str =
await WXIsolate.addIsolateTask<String>(
timeConsumingTask, 'getName');
return str;
}
/// compute 测试
Future<String> getDataByCompute() async {
String str = await compute(timeConsumingTask, 'getName');
return str;
}
/// 耗时任务
static String timeConsumingTask(String str) {
// sleep(Duration(seconds: 3));
int index = 0;
while(index < 2000000000) {
index ++;
}
return '$str : jack';
}
}
- isolate封装实现
import 'dart:async';
import 'dart:isolate';
const String WXIsolatePortKey = 'WXIsolatePortKey';
/// 子isolate可以调用主isolate中定义以static修饰的静态变量(与函数)及写在类外面的全局变量(与函数)
class WXIsolate {
static Future<dynamic> addIsolateTask<T>(Function(T) callback, T arguments) async {
/// 创建管道
ReceivePort receivePort = ReceivePort();
/// 创建新的Isolate
Isolate isolate = await Isolate.spawn<SendPort>(packageTask, receivePort.sendPort);
/// 创建Completer,用于返回future
final Completer<T> result = Completer<T>();
SendPort sendPort2;
/// 监听管道消息
receivePort.listen((data) {
if (data is Map<String, dynamic> && data.containsKey(WXIsolatePortKey)) {
/// 拿到receivePort2.sendPort
sendPort2 = data[WXIsolatePortKey];
/// 将参数及耗时任务通过sendPort2发送给子isolate
Map param = {'message': arguments, 'callback': callback};
sendPort2.send(param);
} else {
/// 这边收到最终执行完的结果
result.complete(data);
/// 拿到结果后关闭
closeIsolate(isolate, receivePort);
}
}, onError: (error) {
closeIsolate(isolate, receivePort);
});
return result.future;
}
}
void packageTask(SendPort sendPort) {
ReceivePort receivePort2 = ReceivePort();
SendPort sendPort2 = receivePort2.sendPort;
receivePort2.listen((data) {
/// 监听回调,拿到主isolate的耗时操作并执行
Function callback = data['callback'];
/// 将执行完的结果再发送给主isolate
sendPort.send(callback(data['message']));
});
/// 将receivePort2.sendPort发送个主isolate
sendPort.send({WXIsolatePortKey: sendPort2});
}
/// 关闭通道及isolate
void closeIsolate(Isolate isolate, ReceivePort receivePort) {
receivePort.close();
isolate?.kill(priority: Isolate.immediate);
}
完整demo链接