跨平台技术演进及Flutter未来( 五 )


跨平台技术演进及Flutter未来

文章插图
上图是从源码中提炼而来的任务处理流程 , 比官方流程图更容易理解一些复杂流程的时序问题 , 后续会专门讲解个中原由 。Flutter的任务队列处理机制跟Android的消息队列处理相通 , 只不过Flutter分为Task和MicroTask两种类型 , 引擎和Dart虚拟机的事件以及Future都属于Task , Dart层执行scheduleMicrotask所产生的属于Microtask 。
每次Flutter引擎在消费任务时调用FlushTasks方法 , 遍历整个延迟任务队列delayedtasks , 将已到期的任务加入task队列 , 然后开始处理任务 。
  • Step 1: 检查task , 当task队列不为空 , 先执行一个task;
  • Step 2: 检查microTask , 当microTask不为空 , 则执行microTask;不断循环Step 2 直到microTask队列为空 , 再回到执行Step 1;
可简单理解为先处理完所有的Microtask , 然后再处理Task 。因为scheduleMicrotask方法的调用自身就处于一个Task , 执行完当前的task , 也就意味着马上执行该Microtask 。
了解了其工作机制 , 再来看看这4个Task Runner的具体工作内容 。
  • Platform Task Runner:运行在Android或者iOS的主线程 , 尽管阻塞该线程并不会影响Flutter渲染管道 , 平台线程建议不要执行耗时操作;否则可能触发watchdog来结束该应用 。比如Android、iOS都是使用平台线程来传递用户输入事件 , 一旦平台线程被阻塞则会引起手势事件丢失 。
  • UI Task Runner: 运行在ui线程 , 比如1.ui , 用于引擎执行root isolate中的所有Dart代码 , 执行渲染与处理Vsync信号 , 将widget转换生成Layer Tree 。除了渲染之外 , 还有处理Native Plugins消息、Timers、Microtasks等工作;
  • GPU Task Runner:运行在gpu线程 , 比如1.gpu , 用于将Layer Tree转换为具体GPU指令 , 执行设备GPU相关的skia调用 , 转换相应平台的绘制方式 , 比如OpenGL, vulkan, metal等 。每一帧的绘制需要UI Runner和GPU Runner配合完成 , 任何一个环节延迟都可能导致掉帧;
  • IO Task Runner:运行在io线程 , 比如1.io , 前3个Task Runner都不允许执行耗时操作 , 该Runner用于将图片从磁盘读取出来 , 解压转换为GPU可识别的格式后 , 再上传给GPU线程 。为了能访问GPU , IO Runner跟GPU Runner的Context在同一个ShareGroup 。比如ui.image通过异步调用让IO Runner来异步加载图片 , 该线程不能执行其他耗时操作 , 否则可能会影响图片加载的性能 。
 
5. Dart虚拟机工作Flutter引擎启动会创建Dart虚拟机以及Root Isolate 。DartVM自身也拥有自己的Isolate , 完全由虚拟机自己管理的 , Flutter引擎也无法直接访问 。Dart的UI相关操作 , 是由Root Isolate通过Dart的C++调用 , 或者是发送消息通知的方式 , 将UI渲染相关的任务提交到UIRunner执行 , 这样就可以跟Flutter引擎相关模块进行交互 。
何为Isolate , 从字面上理解是“隔离” , isolate之间是逻辑隔离的 。Isolate中的代码也是按顺序执行 , 因为Dart没有共享内存的并发 , 没有竞争的可能性 , 故不需要加锁 , 也没有死锁风险 。对于Dart程序的并发则需要依赖多个isolate来实现 。
跨平台技术演进及Flutter未来

文章插图
图解: