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里!