Flutter--線程模型

Flutter線程模型

  • isolate是通過Flutter Engine層面的一個線程來實現的,Flutter Engine線程的創建和管理是由embedder負責的,下面是Flutter Engine的運行架構

  • 在這裏插入圖片描述

  • Platform Task Runner

    • 它是Flutter Engine的主Task Runner,既可以處理與Engine的交互也可以處理來自native平臺的交互,他類似與Android Main Thread, IOS的Main Thread。每一個Flutter應用啓動的時候都會創建一個Engine實例,Engine創建的時候會創建一個Platform Thread供Platform Runner使用,Flutter Engine中很多模塊都是廢縣丞安全的,即使Platform Thread被阻塞,也不會直接導致應用卡頓,但是儘量不要長時間卡住Platform Thread,避免應用被系統的WatchDog強行中止。
  • UI Task Runner

    • 它用於執行Dart root isolate代碼,Root isolate在引擎啓動的時候綁定了不少flutter所需要的方法,從而使其具備調度/提交/渲染幀的能力,該流程如下

      • Root isolate通知Flutter Engine有幀需要渲染
      • 渲染會生成Layer Tree並交給Flutter Engine, 但是此時僅僅生成了需要哦描繪的內容
      • 創建並更新Layer Tree,這個Layer Tree會決定顯示在屏幕上的內容
    • 除了渲染相關邏輯之外Root Isolate還是處理來自Native Plugins的消息,Timers,Microtasks和異步IO等操作。Root Isolate負責創建管理的Layer Tree最終決定繪製到屏幕上的內容。因此這個線程的過載會直接導致卡頓掉幀。

  • GPU Task Runner

    • 它用於執行與設備GPU相關的調用,它可以將UI Task Runner 生成的Layer Tree所提供的信息轉化爲實際的GPU指令。GPU Runner會根據目前幀被執行的進度向UI Task Runner要求下一幀的數據,在任務繁重時,UI Task Runner會延遲任務進程,這種機制來確保GPU Task Runner 不至於出現過載現象,同時避免了UI Task Runner不必要的消耗
  • IO Task Runner

    • IO Task Runner 的運行線程也對應着平臺的子線程,我們發現之前三個Runner對耗時操作比較敏感,當他們出現過載的時候,都會伴隨着應用的卡頓。所以IO Task Runner來負責他們處理不了的任務—IO操作。IO Runner的主要功能是做一些預先處理的讀取操作,然後將準備好的數據上交給GPU Runner。彷彿IO Runner是GPU Runner的一個助手

isolate

  • 在Flutter中所有dart代碼都是在isolate上運行的即dart程序的併發都是運行多個isolate的結果,通常情況下,應用都是運行在main isolate中,但是isolate是有自己的內存和單線程控制的運行實體,在內存上是完全隔離的,所以多個isolate之間無法共享內存,必須通過port通信纔可以,這也是他和線程之間的區別

創建單獨的isolate(仍受Root isolate控制)

  • 正如上面談到的isolate和線程之間的區別,創建一個單獨的isolate,可以在UI Task Runner運算量過大的時候,單獨進行數據運算,所以單獨的isolate顯得比較重要:
import 'dart:isolate';

main() async {

  // isolate的創建必須要有通過ReceivePort創建的SendPort
  final receivePort = new ReceivePort();


  // 創建Isolate
  await Isolate.spawn(_isolate, receivePort.sendPort);


  // 發送第一個message(即sendPort)
  var sendPort = await receivePort.first;


  // 發送信息
  var message = await sendReceive(sendPort, "Send1");
  print('received $message');
  message = await sendReceive(sendPort, "Send2");
  print('received $message');
}


// 入口函數
_isolate(SendPort sendPort) async {
  // 實例化一個ReceivePort以接收消息
  var port = new ReceivePort();


  // 將傳入的sendPort發送給當前Isolate, 以便當前Isolate可以給他發送消息
  sendPort.send(port.sendPort);


  // 監聽port並從中獲取消息
  await for (var message in port) {
    var data = message[0];
    SendPort replyTo = message[1];
    replyTo.send('reply: ' + data);
//    print('reply' + data);
//    print('reply' + replyTo.toString());
    if (message[0] == "Send2") {
      port.close();
    }
  }
}


Future sendReceive(SendPort sendPort, message) {
  ReceivePort receivePort = new ReceivePort();
  // 將信息傳遞給宿主Isolate
  sendPort.send([message, receivePort.sendPort]);
  // 返回當前Stream,類似一個管道
  return receivePort.first;
}
  • 代碼執行流程:main->創建單獨的isolate->snedReceive並將當前發的receivePort的sendPort傳入->sendPort將信息發送給宿主Isolate->_Isolate將信息讀取併發送回main->main中將結果打印出來

  • 運行結果:

received reply: Send1
received reply: Send2
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章