四、Flutter的渲染机制之BuildOwner

从Flutter的渲染机制以及setState()背后的原理这篇文章我们简单提到了element交由BuildOwner管理生命周期,BuildOwner会调用

final Element element = _dirtyElements[index];
element.rebuild();`

来实现所有脏element的构建

  • 1.scheduleBuildFor的实现
  /// Adds an element to the dirty elements list so that it will be rebuilt
  /// when [WidgetsBinding.drawFrame] calls [buildScope].
  void scheduleBuildFor(Element element) {
    if (!_scheduledFlushDirtyElements && onBuildScheduled != null) {
      onBuildScheduled!();
    }
    _dirtyElements.add(element);
    element._inDirtyList = true;
  }
  • 2.BuildOwner的初始化
/// The glue between the widgets layer and the Flutter engine.
mixin WidgetsBinding on BindingBase, ServicesBinding, SchedulerBinding, GestureBinding, RendererBinding, SemanticsBinding {
  @override
  void initInstances() {
    super.initInstances();

    _buildOwner = BuildOwner();
    buildOwner!.onBuildScheduled = _handleBuildScheduled;
    window.onLocaleChanged = handleLocaleChanged;
    window.onAccessibilityFeaturesChanged = handleAccessibilityFeaturesChanged;
    SystemChannels.navigation.setMethodCallHandler(_handleNavigationInvocation);

onBuildScheduled被赋值为_handleBuildScheduled

  void _handleBuildScheduled() {
    // If we're in the process of building dirty elements, then changes
    // should not trigger a new frame.
    ensureVisualUpdate();
  }
  void ensureVisualUpdate() {
    switch (schedulerPhase) {
      case SchedulerPhase.idle:
    // 重点在这里.
      case SchedulerPhase.postFrameCallbacks:
        scheduleFrame();
        return;
      case SchedulerPhase.transientCallbacks:
      case SchedulerPhase.midFrameMicrotasks:
      case SchedulerPhase.persistentCallbacks:
        return;
    }
  }
  void scheduleFrame() {
    //ensureFrameCallbacksRegistered其实是对window的方法进行赋值
    //void ensureFrameCallbacksRegistered() {
    //    window.onBeginFrame ??= _handleBeginFrame;
    //    window.onDrawFrame ??= _handleDrawFrame;
    //}
    ensureFrameCallbacksRegistered();
    window.scheduleFrame();
    _hasScheduledFrame = true;
  }

这里是调用native方法了

void scheduleFrame() native 'PlatformConfiguration_scheduleFrame';

....省略之间的过程(暂时还没搞清这个过程是怎么走的,但是不影响后续流程)

  • 3.从Flutter原生的过程
    flutter项目里打开原生Android工程
import io.flutter.embedding.engine.FlutterEngine;

点击FlutterEngine可以查看内部实现,找到FlutterJNI

//FlutterJNI里的一个实现方法
  private static void asyncWaitForVsync(final long cookie) {
    if (asyncWaitForVsyncDelegate != null) {
      asyncWaitForVsyncDelegate.asyncWaitForVsync(cookie);
    } 
  }

这是一个定义好的接口

  public interface AsyncWaitForVsyncDelegate {
    void asyncWaitForVsync(final long cookie);
  }

点击AsyncWaitForVsyncDelegateVsyncWaiter.java找到对应的实现

  private final FlutterJNI.AsyncWaitForVsyncDelegate asyncWaitForVsyncDelegate =
      new FlutterJNI.AsyncWaitForVsyncDelegate() {
        @Override
        public void asyncWaitForVsync(long cookie) {
          //postFrameCallback:监听系统垂直同步信号,收到下一个垂直信号时回调触发
          Choreographer.getInstance()
              .postFrameCallback(
                  new Choreographer.FrameCallback() {
                    @Override
                    public void doFrame(long frameTimeNanos) {
                      long delay = System.nanoTime() - frameTimeNanos;
                      if (delay < 0) {
                        delay = 0;
                      }
                    //最后调用flutterJNI.onVsync方法
                      flutterJNI.onVsync(delay, refreshPeriodNanos, cookie);
                    }
                  });
        }
      };

流程:postFrameCallback:监听系统垂直同步信号,
收到下一个垂直信号时回调触发doFrame,
最后调用flutterJNI.onVsync方法进入c++流程中

  public void onVsync(long frameDelayNanos, long refreshPeriodNanos, long cookie) {
    nativeOnVsync(frameDelayNanos, refreshPeriodNanos, cookie);
  }

....省略之间c++的过程
再来到我们的Flutter engine
源码地址:https://github.com/flutter/engine

lib/ui/window/platform_configuration.cc

void PlatformConfiguration::BeginFrame(fml::TimePoint frameTime,
                                       uint64_t frame_number) {
  tonic::LogIfError(
      tonic::DartInvoke(begin_frame_.Get(), {
                                                Dart_NewInteger(microseconds),
                                                Dart_NewInteger(frame_number),
                                            }));
  // 执行 microTask 
  UIDartState::Current()->FlushMicrotasksNow();

  tonic::LogIfError(tonic::DartInvokeVoid(draw_frame_.Get()));
}

DartInvoke(begin_frame... FlushMicrotasksNow DartInvokeVoid(draw_frame...
⤵️

window.onBeginFrame
执行 MicroTask 队列
window.onDrawFrame
scheduler/binding.dart

  void ensureFrameCallbacksRegistered() {
    window.onBeginFrame ??= _handleBeginFrame;
    window.onDrawFrame ??= _handleDrawFrame;
  }
  • handleBeginFrame的实现
  void handleBeginFrame(Duration? rawTimeStamp) {
    try {
      //handleBeginFrame 触发,执行_transientCallbacks集合中的任务。
      //顾名思义,_transientCallbacks 是一个临时性的集合,往往通过 Ticker 向里面添加一些动画任务。
      //TRANSIENT FRAME CALLBACKS
      _schedulerPhase = SchedulerPhase.transientCallbacks;
      final Map callbacks = _transientCallbacks;
      callbacks.forEach((int id, _FrameCallbackEntry callbackEntry) {
        if (!_removedIds.contains(id))
          _invokeFrameCallback(callbackEntry.callback, _currentFrameTimeStamp!, callbackEntry.debugStack);
      });
      _removedIds.clear();
    } finally {
      //由 C++ 调度 MicroTask
      _schedulerPhase = SchedulerPhase.midFrameMicrotasks;
    }
  }
  • handleDrawFrame的实现
  void handleDrawFrame() {
    assert(_schedulerPhase == SchedulerPhase.midFrameMicrotasks);
    _frameTimelineTask?.finish(); // end the "Animate" phase
    try {
      // handleDrawFrame 触发,执行 _persistentCallbacks 集合中的任务。
      // 这些任务是一帧绘制所必须的,例如 build、layout、paint。
      // PERSISTENT FRAME CALLBACKS
      _schedulerPhase = SchedulerPhase.persistentCallbacks;
      for (final FrameCallback callback in _persistentCallbacks)
        _invokeFrameCallback(callback, _currentFrameTimeStamp!);

      // handleDrawFrame 触发,在上一个的任务集合执行完成后,执行 _postFrameCallbacks集合中的任务。
      // 由于系统已经 layout ,所以可以在这个阶段获取 widget 的尺寸信息(RenderBox、RenderSliver)。
      // POST-FRAME CALLBACKS
      _schedulerPhase = SchedulerPhase.postFrameCallbacks;
      final List localPostFrameCallbacks =
          List.of(_postFrameCallbacks);
      _postFrameCallbacks.clear();
      for (final FrameCallback callback in localPostFrameCallbacks)
        _invokeFrameCallback(callback, _currentFrameTimeStamp!);
    } finally {
      // handleDrawFrame 触发,所有的任务都已执行完成,处于空闲阶段。
      _schedulerPhase = SchedulerPhase.idle;
      _frameTimelineTask?.finish(); // end the Frame
    }
  }

总体流程图:


总体流程图
  • 参考资料
    Flutter 核心渲染流程分析 [完结篇]

你可能感兴趣的:(四、Flutter的渲染机制之BuildOwner)