前言
Dart是单线程的,Dart提供了Isolate,isolate提供了多线程的能力。但作为多线程能力的,却内存不能共享。但同样的内存不能共享,那么就不存在锁竞争问题。
举个例子来展示作用
如果一段代码执行事件很长,flutter如何开发。 基本页面代码(一段代码)
ElevatedButton(
child: Text("登录"),
onPressed: () {
执行运行代码();
}
延时代码块
String work(int value){
print("work start");
sleep(Duration(seconds:value));
print("work end");
return "work complete:$value";
}
第一种:直接执行运行代码(延时5秒)
执行运行代码() {
work(5);
}
结果: 5秒卡的死死的
第二种:async执行运行代码(延时5秒)
执行运行代码() async{
work(5);
}
结果: 5秒依旧卡的死死的
------------------------------------------------我是分割线--------------------------------------------------
why?在dart中,async不是异步计算么?(循环机制下篇讲)因为我们仍旧是在同一个UI线程中做运算,异步只是说我可以先运行其他的,等我这边有结果再返回,但是,我们的计算仍旧是在这个UI线程,仍会阻塞UI的刷新,异步只是在同一个线程的并发操作。
第三种:ioslate执行运行代码(延时5秒)
但是由于dart中的Isolate比较重量级,UI线程和Isolate中的数据的传输比较复杂,因此flutter为了简化用户代码,在foundation库中封装了一个轻量级compute操作。
执行运行代码() async{
var result = await compute(work, 5);
print(result);
}
结果: 居然不卡顿了
使用说明
compute的使用还是有些限制,它没有办法多次返回结果,也没有办法持续性的传值计算,每次调用,相当于新建一个隔离,如果调用过多的话反而会适得其反。我们需要根据不同的业务选择用compute和isolate
Future<dynamic> work(int value) async{
//接收消息管道
ReceivePort rp = new ReceivePort();
//发送消息管道
SendPort port = rp.sendPort;
Isolate isolate = await Isolate.spawn(workEvent, port);
//发送消息管道2
final sendPort2 = await rp.first;
//返回应答数据
final answer = ReceivePort();
sendPort2.send([answer.sendPort, value]);
return answer.first;
}
void workEvent(SendPort port) {
//接收消息管道2
final rPort = ReceivePort();
SendPort port2 = rPort.sendPort;
// 将新isolate中创建的SendPort发送到主isolate中用于通信
port.send(port2);
rPort.listen((message) {
final send = message[0] as SendPort;
send.send(work(5));
});
}
基本方法
//恢复 isolate 的使用
isolate.resume(isolate.pauseCapability);
//暂停 isolate 的使用
isolate.pause(isolate.pauseCapability);
//结束 isolate 的使用
isolate.kill(priority: Isolate.immediate);
//赋值为空 便于内存及时回收
isolate = null;
两个进程都双向绑定了消息通信的通道,即使新的Isolate中的任务完成了,它的进程也不会立刻退出,因此,当使用完自己创建的Isolate后,最好调用isolate.kill(priority: Isolate.immediate);将Isolate立即杀死。
用Future还是isolate?
future使用场景:
isolate使用场景:
- 繁重的处理可能要花一些时间才能完成
- 网络加载大图
- 图片处理
|