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
发布了175 篇原创文章 · 获赞 56 · 访问量 3万+

猜你喜欢

转载自blog.csdn.net/qq_39424143/article/details/105018979