0x00 前言
Flutter的程式碼都是預設跑在root isolate上的,那麼Flutter中能不能自己建立一個isolate呢?當然可以!,接下來我們就自己建立一個isolate!
0x01 dart:isolate
有關isolate的程式碼,都在isolate.dart
檔案中,裡面有一個生成isolate的方法:
external static Future<Isolate> spawn<T>(
void entryPoint(T message), T message,
{bool paused: false,
bool errorsAreFatal,
SendPort onExit,
SendPort onError});
複製程式碼
spawn
方法,必傳引數有兩個,函式entryPoint和引數message,其中
-
函式
函式必須是頂級函式或靜態方法
-
引數
引數裡必須包含
SendPort
0x02 開始動手寫
建立的步驟,寫在程式碼的註釋裡
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);
}
複製程式碼
0x03 執行結果
直接執行程式就會在log裡看到如下的列印:
flutter: 6765
複製程式碼
0x04 isolate有什麼用?
說了這麼久,為什麼要建立自己的isolate?有什麼用?
因為Root isolate會負責渲染,還有UI互動,如果我們有一個很耗時的操作呢?前面知道isolate裡是一個event loop(事件迴圈),如果一個很耗時的task一直在執行,那麼後面的UI操作都被阻塞了,所以如果我們有耗時的操作,就應該放在isolate裡!