温故知新-RendererBinding

46 阅读2分钟

RendererBinding

RendererBinding 顾名思义就是处理渲染相关的事情,它是flutter引擎与Render Tree之间的粘合剂,同时管理着多个独立的Render Tree,以及PipelineOwner的管理。

initInstances

  • 创建PipelineOwner
  • 设置platformDispatcher的回调
  • 添加SchedulerBinding的持久帧回调
 void initInstances() {
    super.initInstances();
    _instance = this;
    _rootPipelineOwner = createRootPipelineOwner();
    platformDispatcher
      ..onMetricsChanged = handleMetricsChanged
      ..onTextScaleFactorChanged = handleTextScaleFactorChanged
      ..onPlatformBrightnessChanged = handlePlatformBrightnessChanged;
    addPersistentFrameCallback(_handlePersistentFrameCallback);
    ......
    rootPipelineOwner.attach(_manifold);
  }

handleMetricsChanged

平台的指标数据(比如屏幕旋转、窗口大小改变时)发生改变,通知Flutter做出数据更新,并强制调用一帧。
[ViewConfiguration]保存着根渲染对象的布局约束

void handleMetricsChanged() {
    bool forceFrame = false;
    for (final RenderView view in renderViews) {
      forceFrame = forceFrame || view.child != null;
      view.configuration = createViewConfigurationFor(view);
    }
    if (forceFrame) {
      scheduleForcedFrame();
    }
  }

drawFrame

drawFrame是RendererBinding最重要的一个方法了,启动PipelineOwner去生成新的一帧。
drawFramehandleDrawFrame调用,而handleDrawFrame方法本身在需要布局和绘制一帧时由引擎自动调用。
这里再复习一下ScheduleBindinghandleBeginFrameonDrawFrame的调用流程。

  1. 动画阶段:handleBeginFrame方法已在 PlatformDispatcher.onBeginFrame 中注册,它会按注册顺序调用所有已在 scheduleFrameCallback 中注册的瞬时帧回调,其中包括所有驱动AnimationController对象的Ticker实例,这意味着所有活动Animation对象都会在此点执行tick;
  2. 微任务:handleBeginFrame返回后,所有由瞬时帧回调调度的微任务都会开始运行。这通常包括来自TickerAnimationController的 Future 回调,这些 Future 回调完成了此帧;

handleBeginFrame之后,将调用platformDispatcher.onDrawFrame注册的 handleDrawFrame,该方法会调用所有持久帧回调,其中最值得注意的是drawFrame方法;

  1. 布局阶段:系统中所有已脏的RenderObject都会被布局;
rootPipelineOwner.flushLayout()
  1. 合成位阶段:所有已脏的RenderObject对象上的合成位都会被更新。
rootPipelineOwner.flushCompositingBits();
  1. 绘制阶段:系统中所有已脏的RenderObject都会被重新绘制Layer tree
rootPipelineOwner.flushPaint();
  1. 合成阶段:图层树转换为Scene并发送到 GPU;
for (final RenderView renderView in renderViews) {
    // this sends the bits to the GPU 
    renderView.compositeFrame(); 
}
  1. 语义阶段:系统中所有脏的RenderObject的语义都会更新,这将生成语义树;
void _handlePersistentFrameCallback(Duration timeStamp) {
    drawFrame();
    ......
}
void drawFrame() {
    rootPipelineOwner.flushLayout();
    rootPipelineOwner.flushCompositingBits();
    rootPipelineOwner.flushPaint();
    if (sendFramesToEngine) {
      for (final RenderView renderView in renderViews) {
        renderView.compositeFrame(); // this sends the bits to the GPU
      }
      rootPipelineOwner.flushSemantics();
      _firstFrameSent = true;
    }
  }