我们知道rebuild widget一般是在State里面调用setState,那么rebuild的原理是什么样的呢?
setState会调用element的markNeedsBuild 标记需要rebuild的element,然后调用BuildOwner的
scheduleBuildFor
setState => element.markNeedsBuild(){
//标记脏了,需要重新绘制
_dirty = true;
//每个element都持有同一个owner
//buildowner在WidgetsFlutterBinding
//初始化时创建,并且设置了build回调 buildOwner!.onBuildScheduled =
// _handleBuildScheduled;
owner!.scheduleBuildFor(this);
}
scheduleBuildFor 里面然后调用_handleBuildScheduled
/// Adds an element to the dirty elements list so that it will be rebuilt
/// when [WidgetsBinding.drawFrame] calls [buildScope].
//将需要build的element添加到列表
//当WidgetsBinding.drawFrame调用buildScope时会用到
=>BuildOwner.scheduleBuildFor(){
if (!_scheduledFlushDirtyElements && onBuildScheduled != null) {
_scheduledFlushDirtyElements = true;
onBuildScheduled!();
}
_dirtyElements.add(element);
element._inDirtyList = true;
}
调用栈
==>_handleBuildScheduled()
==>ensureVisualUpdate()
=>SchedulerBinding.scheduleFrame(){
ensureFrameCallbacksRegistered();
window.scheduleFrame();
_hasScheduledFrame = true;
}
=>window.scheduleFrame();
=>platformDispatcher.scheduleFrame()
=> native PlatformConfiguration_scheduleFrame
然后调用到native层
==>platform_configuration.cc#ScheduleFrame
=> runtime_controller.cc#ScheduleFrame
=>engine.cc#ScheduleFrame
=>animator::RequestFrame
//等待同步信号
=>animator.cc#Animator::AwaitVSync()
=>animator.cc#Animator::BeginFrame
=>shell.cc#OnAnimatorBeginFrame
=>engine_->BeginFrame(frame_target_time, frame_number)
=>runtime_controller_->BeginFrame(frame_time, frame_number);
=>platform_configuration->BeginFrame(frame_time, frame_number){
tonic::LogIfError(
//调用dart层的 hooks.dart#_beginFrame
tonic::DartInvoke(begin_frame_.Get(), {
Dart_NewInteger(microseconds),
Dart_NewInteger(frame_number),
}));
UIDartState::Current()->FlushMicrotasksNow();
native在调用dart层的hooks#_drawFrame
//调用dart层的 hooks.dart#_drawFrame
tonic::LogIfError(tonic::DartInvokeVoid(draw_frame_.Get()));
}
//这里会走两个分支,1执行begin_frame_ 2.执行draw_frame_
分支1:=>tonic::LogIfError(
tonic::DartInvoke(begin_frame_.Get(), {
Dart_NewInteger(microseconds),
Dart_NewInteger(frame_number),
}));
//绘制每一帧之前的回调
=> hooks.dart#_beginFrame
=>platform_dispatcher.dart#_beginFrame
=> window.onBeginFrame
=>SchedulerBinding.dart#_handleBeginFrame
=>handleBeginFrame
==>遍历_transientCallbacks,执行回调
=>调用通过SchedulerBinding.instance!.scheduleFrameCallback注册的回调
//绘制回调
分支2:hooks.dart#_drawFrame
=>windown.onDrawFrame
=>schedulerBinding._handleDrawFrame
//执行_persistentCallbacks,_postFrameCallbacks注册的回调
=>SchedulerBinding.handleDrawFrame()=>
RendererBinding._handlePersistentFrameCallback => WidgetsBinding.drawFrame(){
if (renderViewElement != null)
buildOwner!.buildScope(renderViewElement!);
super.drawFrame(); => RendererBinding.drawFrame()
buildOwner!.finalizeTree();
}
=> RendererBinding.drawFrame(){
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;
}
}
=> void compositeFrame() {
try {
final ui.SceneBuilder builder = ui.SceneBuilder();
final ui.Scene scene = layer!.buildScene(builder);
if (automaticSystemUiAdjustment)
_updateSystemChrome();
_window.render(scene);
scene.dispose();
} finally {
}
}
//rebuild列表里的element
buildScope(){
while(){
_dirtyElements[index].rebuild();
}
}
//赋值window.onDrawFrame= SchedulerBinding._handleDrawFrame
//启动app时scheduleWarmUpFrame无需等到同步信号,第一时间显示最近的缓存数据
runApp(app){
WidgetsFlutterBinding.ensureInitialized()
..scheduleAttachRootWidget(app)
..scheduleWarmUpFrame();
}=>SchedulerBinding.scheduleWarmUpFrame(){
Timer.run(() {
assert(_warmUpFrame);
handleBeginFrame(null);
});
Timer.run(() {
assert(_warmUpFrame);
handleDrawFrame();
// We call resetEpoch after this frame so that, in the hot reload case,
// the very next frame pretends to have occurred immediately after this
// warm-up frame. The warm-up frame's timestamp will typically be far in
// the past (the time of the last real frame), so if we didn't reset the
// epoch we would see a sudden jump from the old time in the warm-up frame
// to the new time in the "real" frame. The biggest problem with this is
// that implicit animations end up being triggered at the old time and
// then skipping every frame and finishing in the new time.
resetEpoch();
_warmUpFrame = false;
if (hadScheduledFrame)
scheduleFrame();
});
}
//WidgetsFlutterBinding RendererBinding初始化注册回调到列表_persistentCallbacks 始终存在列表中
addPersistentFrameCallback(_handlePersistentFrameCallback);
window.scheduleFrame => ScheduleFrame
AwaitVSync =>Animator.cc =>Shell => engine => runtime_controller => platform
java -> dart
FlutterJNI =>
platform_view_android_jni_impl.cc => AndroidShellHolder=>Shell => engine => runtime_controller => platform
=>DartInvoke
RuntimeController 是PlatformConfigurationClient
总结:setState =>对element做标记需要rebuild
由window.scheduleFrame通知native层等待同步信号,需要回调hooks.dart#_beginFrame,hooks.dart#_drawFrame
=>buildOwner.buildScope =>element.rebuild()=>performRebuild =>build()=>
//比较新旧widget Element
_child = updateChild(_child, built, slot);
//layout => Compositing(合成) => paint()
==> RendererBinding.drawFrame(){
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;
}
}
widget比较算法
static bool canUpdate(Widget oldWidget, Widget newWidget) {
return oldWidget.runtimeType == newWidget.runtimeType
&& oldWidget.key == newWidget.key;
}