Flutter 框架执行过程

766 阅读1分钟

上文 Flutter 框架简介 简单介绍了框架的边界和入口,这篇文章主要介绍下 Flutter 框架执行流程。

1. SchedulerPhase

SchedulerPhase 是个枚举类,标识框架调度执行的各个阶段。

enum SchedulerPhase {
  // 空闲阶段,此阶段没有帧调度。会执行 Tasks,microtasks,Timer callbacks 等
  idle,  
  // 由 SchedulerBinding.scheduleFrameCallback 调度,动画执行 _tick 过程在这个阶段执行
  transientCallbacks,
  // 执行上一个阶段调度的 microtasks,如 Future
  midFrameMicrotasks,
  // 由 SchedulerBinding.addPersisitentFrameCallback 调度。build/layout/paint 过程在这里执行
  persistentCallbacks,
  // 由 SchedulerBinding.addPostFrameCallback 调度。通常执行清理和下一帧调度相关工作
  postFrameCallbacks,
}

2. handleBeginFrame

window 的 onBeginFrame 由 SchedulerBinding.handleBeginFrame 处理。

mixin SchedulerBinding on BindingBase {
  ...
  void handleBeginFrame(Duration? rawTimeStamp) {
    ...
    assert(schedulerPhase == SchedulerPhase.idle);
    ...
    try {  
      // TRANSIENT FRAME CALLBACKS  
      Timeline.startSync('Animate', arguments: timelineArgumentsIndicatingLandmarkEvent);  
      _schedulerPhase = SchedulerPhase.transientCallbacks;  
      final Map<int, _FrameCallbackEntry> callbacks = _transientCallbacks;  
      _transientCallbacks = <int, _FrameCallbackEntry>{};  
      callbacks.forEach((int id, _FrameCallbackEntry callbackEntry) {    
        if (!_removedIds.contains(id))      
          _invokeFrameCallback(callbackEntry.callback, _currentFrameTimeStamp!, callbackEntry.debugStack);  
        });  
        _removedIds.clear();
      } finally {  
        _schedulerPhase = SchedulerPhase.midFrameMicrotasks;
      }
  }
  ...
}

可以看到 handleBeginFrame 在 SchedulerPhase.transientCallbacks 阶段,执行了 _transientCallbacks。

Ticker 在 _tick 方法中间接调用 SchedulerBinding.scheduleFrameCallback 将 _tick 加入 transientCallbacks 中,在这里会执行。

3. handleDrawFrame

window 的 onDrawFrame 由 SchedulerBinding.handleDrawFrame 处理。

void handleDrawFrame() {
  ...
  try {
  // PERSISTENT FRAME CALLBACKS  
  _schedulerPhase = SchedulerPhase.persistentCallbacks;  
  for (final FrameCallback callback in _persistentCallbacks)    
    _invokeFrameCallback(callback, _currentFrameTimeStamp!);  
  // POST-FRAME CALLBACKS  
  _schedulerPhase = SchedulerPhase.postFrameCallbacks;  
  final List<FrameCallback> localPostFrameCallbacks =      
    List<FrameCallback>.from(_postFrameCallbacks);  
  _postFrameCallbacks.clear();  
  for (final FrameCallback callback in localPostFrameCallbacks)    
    _invokeFrameCallback(callback, _currentFrameTimeStamp!);  
  } finally {    
    _schedulerPhase = SchedulerPhase.idle;  
  }
}

在 handleDrawFrame 方法中,先后执行了 _persistentCallbacks 和 _postFrameCallbacks。

_persistentCallbacks 中,添加了 RendererBinding 在初始化 initInstances 时添加的 _handlePersistentFrameCallback。

RendererBinding._handlePersistentFrameCallback

void _handlePersistentFrameCallback(Duration timeStamp) {  
  drawFrame();  
  _scheduleMouseTrackerUpdate();
}

这里调用了 drawFrame。注意,这里的 drawFrame 并没有直接调用自己的 drawFrame,而是调用了 WidgetsBinding.drawFrame。

@override
void drawFrame() {
  ...
  try {
    if (renderViewElement != null)
      buildOwner.buildScope(renderViewElement);
    super.drawFrame();
    buildOwner.finalizeTree();
  }
  ...
}

可以看到,这里调用了 buildOwner.buildScope 方法,执行 build 构建过程,最后保存树(Widget)的状态。其中 super.drawFrame 才是调用了 RendererBinding.drawFrame。

RenderBinding.drawFrame

@protected
void drawFrame() {
  assert(renderView != null);
  pipelineOwner.flushLayout();
  pipelineOwner.flushCompositingBits();
  pipelineOwner.flushPaint();
  if (sendFramesToEngine) {  
    renderView.compositeFrame(); // this sends the bits to the GPU  
    pipelineOwner.flushSemantics(); // this also sends the semantics to the OS.  
    _firstFrameSent = true;
  }
}

这里由 pipelineOwner 对象完成 layout、paint、composition 过程。

最后说一下 _postFrameCallbacks,_postFrameCallbacks 在当前帧结束时调用,这个回调只会执行一次,你可以在这个回调中添加需要等待页面渲染结束才执行的某些操作。