从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);
}
点击AsyncWaitForVsyncDelegate
在VsyncWaiter.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 核心渲染流程分析 [完结篇]