深入瞭解Flutter的isolate(2) — 建立自己的isolate

小德_koudle發表於2019-03-04

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,其中

  1. 函式

    函式必須是頂級函式或靜態方法

  2. 引數

    引數裡必須包含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裡!

參考文章

hackernoon.com/are-futures…

相關文章