前面讲了如何建立isolate,这篇文章讲建立isolate的另外一种方法。bash
使用isolates的方法种:app
Compute函数对isolate的建立和底层的消息传递进行了封装,使得咱们没必要关系底层的实现,只须要关注功能实现。异步
首先咱们须要:async
好比,仍是计算斐波那契数列:函数
void main() async{
//调用compute函数,compute函数的参数就是想要在isolate里运行的函数,和这个函数须要的参数
print( await compute(syncFibonacci, 20));
runApp(MyApp());
}
int syncFibonacci(int n){
return n < 2 ? n : syncFibonacci(n-2) + syncFibonacci(n-1);
}
复制代码
运行后的结果以下:post
flutter: 6765
复制代码
是否是很简单,接下来看下compute
函数的源码,这里的代码有点复杂,会把分析的添加到代码的注释里,首先介绍一个compute
函数里用到的函数别名:ui
ComputeCallback<Q, R>
定义以下:this
// Q R是泛型,ComputeCallback是一个有参数Q,返回值为R的函数
typedef ComputeCallback<Q, R> = R Function(Q message);
复制代码
正式看源码:spa
//compute函数 必选参数两个,已经讲过了
Future<R> compute<Q, R>(ComputeCallback<Q, R> callback, Q message, { String debugLabel }) async {
//若是是在profile模式下,debugLabel为空的话,就取callback.toString()
profile(() { debugLabel ??= callback.toString(); });
final Flow flow = Flow.begin();
Timeline.startSync('$debugLabel: start', flow: flow);
final ReceivePort resultPort = ReceivePort();
Timeline.finishSync();
//建立isolate,这个和前面讲的建立isolate的方法一致
//还有一个,这里传过去的参数是用_IsolateConfiguration封装的类
final Isolate isolate = await Isolate.spawn<_IsolateConfiguration<Q, R>>(
_spawn,
_IsolateConfiguration<Q, R>(
callback,
message,
resultPort.sendPort,
debugLabel,
flow.id,
),
errorsAreFatal: true,
onExit: resultPort.sendPort,
);
final R result = await resultPort.first;
Timeline.startSync('$debugLabel: end', flow: Flow.end(flow.id));
resultPort.close();
isolate.kill();
Timeline.finishSync();
return result;
}
@immutable
class _IsolateConfiguration<Q, R> {
const _IsolateConfiguration(
this.callback,
this.message,
this.resultPort,
this.debugLabel,
this.flowId,
);
final ComputeCallback<Q, R> callback;
final Q message;
final SendPort resultPort;
final String debugLabel;
final int flowId;
R apply() => callback(message);
}
void _spawn<Q, R>(_IsolateConfiguration<Q, R> configuration) {
R result;
Timeline.timeSync(
'${configuration.debugLabel}',
() {
result = configuration.apply();
},
flow: Flow.step(configuration.flowId),
);
Timeline.timeSync(
'${configuration.debugLabel}: returning result',
() { configuration.resultPort.send(result); },
flow: Flow.step(configuration.flowId),
);
}
复制代码
import 'dart:async';
import 'dart:io';
import 'dart:isolate';
import 'package:flutter/foundation.dart';
import 'package:flutter/material.dart';
//一个普普统统的Flutter应用的入口
//main函数这里有async关键字,是由于建立的isolate是异步的
void main() async{
runApp(MyApp());
//asyncFibonacci函数里会建立一个isolate,并返回运行结果
print(await asyncFibonacci(20));
}
//这里以计算斐波那契数列为例,返回的值是Future,由于是异步的
Future<dynamic> asyncFibonacci(int n) async{
//首先建立一个ReceivePort,为何要建立这个?
//由于建立isolate所需的参数,必需要有SendPort,SendPort须要ReceivePort来建立
final response = new ReceivePort();
//开始建立isolate,Isolate.spawn函数是isolate.dart里的代码,_isolate是咱们本身实现的函数
//_isolate是建立isolate必需要的参数。
await Isolate.spawn(_isolate,response.sendPort);
//获取sendPort来发送数据
final sendPort = await response.first as SendPort;
//接收消息的ReceivePort
final answer = new ReceivePort();
//发送数据
sendPort.send([n,answer.sendPort]);
//得到数据并返回
return answer.first;
}
//建立isolate必需要的参数
void _isolate(SendPort initialReplyTo){
final port = new ReceivePort();
//绑定
initialReplyTo.send(port.sendPort);
//监听
port.listen((message){
//获取数据并解析
final data = message[0] as int;
final send = message[1] as SendPort;
//返回结果
send.send(syncFibonacci(data));
});
}
int syncFibonacci(int n){
return n < 2 ? n : syncFibonacci(n-2) + syncFibonacci(n-1);
}
复制代码