Isolate
在Dart中实现并发可以用Isolate,它是类似于线程(thread)但不共享内存的独立运行的worker,是一个独立的Dart程序执行环境。其实默认环境就是一个main isolate。
基本使用
library flutter_flutterisolate2;
import 'dart:async';
import 'dart:isolate';
main() async{
//1.创建一个和isoLate环境交流的Port
var receivePort = new ReceivePort();
//2.创建一个隔离isolate并且提供用于回执的sendPort,receivePort.sendPort是一个给当前receive发消息的sendPort
await Isolate.spawn(speak, receivePort.sendPort);
//5.现在需要一个sendPort给isolate发送消息
SendPort sendPort = await receivePort.first;
//6. 利用sendPort给isoLate发送一个消息
var resultFromIsoLate = await sendMessage2IsoLate(sendPort, 'apple');
//8.打印来自于isolate的执行结果
print(resultFromIsoLate);
resultFromIsoLate = await sendMessage2IsoLate(sendPort, 'banana');
print(resultFromIsoLate);
}
//3.创建用于在新isolate执行的函数speak
speak(SendPort sendPort) async{
//4.现在提供给主isolate一个用于给子isolate发消息的sendPort
var receivePort = new ReceivePort();
sendPort.send(receivePort.sendPort);
//单次读取
// var msgFromMainIsoLate = await receivePort.first;
// var msg = msgFromMainIsoLate[0];
// SendPort replyTo = msgFromMainIsoLate[1];
// replyTo.send("i like eat "+ msg);
//7. 读取receivePort并且回传消息, receivePort看起来是一个可迭代器
await for (var r in receivePort){
var msg = r[0];
SendPort replyTo = r[1];
replyTo.send("i like eat "+ msg);
}
}
//如果需要关闭,使用receivePort.close
//发送一条消息给isolate
Future sendMessage2IsoLate(SendPort sendPort, String msg) {
ReceivePort receivePort = ReceivePort();
sendPort.send([msg, receivePort.sendPort]);
return receivePort.first;
}
耗时计算解决案例(compute)
compute只能完成单次isolate交互,无法支持,适合部分简单场景
注意:web模式下似乎没有效果!!!
import 'package:flutter/material.dart';
import 'package:flutter/foundation.dart';
class TestWidget extends StatefulWidget {
@override
State<StatefulWidget> createState() {
return TestWidgetState();
}
}
class TestWidgetState extends State<TestWidget> {
int _count = 0;
@override
Widget build(BuildContext context) {
return Material(
child: Center(
child: Column(
children: <Widget>[
Container(
width: 100,
height: 100,
child: CircularProgressIndicator(),
),
FlatButton(
onPressed: () async {
_count = countEven(1000000000);
setState(() {});
},
child: Text(
_count.toString(),
)),
],
mainAxisSize: MainAxisSize.min,
),
),
);
}
//计算偶数的个数
static int countEven(int num) {
int count = 0;
while (num > 0) {
if (num % 2 == 0) {
count++;
}
num--;
}
return count;
}
}
耗时异步为什么解决不了卡顿?
static Future<int> asyncCountEven(int num) async{
int count = 0;
while (num > 0) {
if (num % 2 == 0) {
count++;
}
num--;
}
return count;
}
仍然卡顿,说明异步是解决不了问题的,为什么?因为我们仍旧是在同一个UI线程中做运算,异步只是说我可以先运行其他的,等我这边有结果再返回,但是,记住,我们的计算仍旧是在这个UI线程,仍会阻塞UI的刷新,异步只是在同一个线程的并发操作。
isolate解决方法
static Future<dynamic> isolateCountEven(int num) async {
final response = ReceivePort();
await Isolate.spawn(countEvent2, response.sendPort);
final sendPort = await response.first;
final answer = ReceivePort();
sendPort.send([answer.sendPort, num]);
return answer.first;
}
static void countEvent2(SendPort port) {
final rPort = ReceivePort();
port.send(rPort.sendPort);
rPort.listen((message) {
final send = message[0] as SendPort;
final n = message[1] as int;
send.send(countEven(n));
});
}