前面講了如何建立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);
}
複製代碼