有状态的widget(StatefulWidget) UI刷新要调用setState. setState做了什么实现的页面刷新呢, 刷新流程是怎样的呢?
上代码
@protected
void setState(VoidCallback fn) {
...
_element.markNeedsBuild();
}
void markNeedsBuild() {
...
if (dirty)
return;
_dirty = true;
owner.scheduleBuildFor(this); ///关键代码
}
插播提问: owner是谁?
- BuildOwner _owner;
@mustCallSuper
void mount(Element parent, dynamic newSlot) {
...
_parent = parent;
if (parent != null)
_owner = parent.owner;
...
}
看源码可知, 子 element 和父 element 公用一个 _owner.
所以, 要确定 _owner 是谁, 先要确定 root element 是谁?
看源码注释我们发现一个抽象类: RootRenderObjectElement
/// The element at the root of the tree.
///
/// Only root elements may have their owner set explicitly. All other
/// elements inherit their owner from their parent.
abstract class RootRenderObjectElement extends RenderObjectElement
接着找到继承了RenderObjectToWidgetElement的类: RootRenderObjectElement, 至此我们就找到了root element的类名
/// A [RootRenderObjectElement] that is hosted by a [RenderObject].
///
/// This element class is the instantiation of a [RenderObjectToWidgetAdapter]
/// widget. It can be used only as the root of an [Element] tree (it cannot be
/// mounted into another [Element]; it's parent must be null).
///
/// In typical usage, it will be instantiated for a [RenderObjectToWidgetAdapter]
/// whose container is the [RenderView] that connects to the Flutter engine. In
/// this usage, it is normally instantiated by the bootstrapping logic in the
/// [WidgetsFlutterBinding] singleton created by [runApp].
class RenderObjectToWidgetElement<T extends RenderObject> extends RootRenderObjectElement
1.1 确定root element及owner
renderViewElement就是root element.
buildOwner就是我们要找的owner, 他在WidgetsBinding.initInstances方法内初始化的
mixin WidgetsBinding on BindingBase, ServicesBinding, SchedulerBinding, GestureBinding, RendererBinding, SemanticsBinding {
void attachRootWidget(Widget rootWidget) {
_readyToProduceFrames = true;
_renderViewElement = RenderObjectToWidgetAdapter<RenderBox>(
container: renderView,
debugShortDescription: '[root]',
child: rootWidget,
).attachToRenderTree(buildOwner, renderViewElement as RenderObjectToWidgetElement<RenderBox>);
}
RenderObjectToWidgetElement<T> attachToRenderTree(BuildOwner owner, [ RenderObjectToWidgetElement<T> element ]) {
///空判断
if (element == null) {
owner.lockState(() {
element = createElement();
assert(element != null);
///给element赋值owner
element.assignOwner(owner);
});
///rebuild
owner.buildScope(element, () {
///因为是root element, 所以super为null
element.mount(null, null);
});
///首次VSYNC注册流程
SchedulerBinding.instance.ensureVisualUpdate();
}
///不为空: markNeedsBuild, 标记为脏,
else {
element._newWidget = this;
element.markNeedsBuild();
}
return element;
}
void assignOwner(BuildOwner owner) {
_owner = owner;
}
1.2 owner初始化
mixin WidgetsBinding on BindingBase, ServicesBinding, SchedulerBinding, GestureBinding, RendererBinding, SemanticsBinding {
@override
void initInstances() {
super.initInstances();
...
///创建 owner
_buildOwner = BuildOwner();
buildOwner.onBuildScheduled = _handleBuildScheduled;
...
}
}
确定了owner, 接着往下看.
///BuildOwner
void scheduleBuildFor(Element element) {
...
if (!_scheduledFlushDirtyElements && onBuildScheduled != null) {
_scheduledFlushDirtyElements = true;
///这是一个回调, 在WidgetsBinding.initInstances初始化的
///也是注册vsync信号
onBuildScheduled(); ///参见1.3
}
///添加到脏列表
_dirtyElements.add(element);
element._inDirtyList = true;
}
1.3 vsync 垂直信号注册
在1.2 owner初始化可知: onBuildScheduled回调调用的是 _handleBuildScheduled方法;
void _handleBuildScheduled() {
...
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() {
if (_hasScheduledFrame || !framesEnabled)
return;
assert(() {
if (debugPrintScheduleFrameStacks)
debugPrintStack(label: 'scheduleFrame() called. Current phase is $schedulerPhase.');
return true;
}());
ensureFrameCallbacksRegistered(); ///初始化vsync回调
window.scheduleFrame(); ///注册vsync信号
_hasScheduledFrame = true;
}
@protected
void ensureFrameCallbacksRegistered() {
///两个关键回调赋值, engine层的vsync信号到来时会回调他俩
window.onBeginFrame ??= _handleBeginFrame;
window.onDrawFrame ??= _handleDrawFrame;
}
///window.dart
///这里的native关键字类似于java JNI的使用, 去调用engine层对应的C++方法
///该方法主要注册了vsync信号, 当vsync信号来到, 回调到framework层, 去刷新标记为dirt的脏element
void scheduleFrame() native 'PlatformConfiguration_scheduleFrame';
2.1 engine层
接下来是engine层的代码, 贴一个大佬的文章:
Flutter渲染机制—UI线程
engine层的 c++代码就略过了, 感兴趣的小伙伴自行查看代码
engine github地址, 我这里直接贴流程图了
-
VSYNC注册流程图
-
Engine层处理流程图
-
Framework层处理流程图
3.1 vsync信号到来时回调onBeginFrame和onDrawFrame
当vsync信号到来时, engine会调用framework层window类的两个回调
onBeginFrame和onDrawFrame
///window.dart
void _handleBeginFrame(Duration rawTimeStamp) {
if (_warmUpFrame) {
assert(!_ignoreNextEngineDrawFrame);
_ignoreNextEngineDrawFrame = true;
return;
}
handleBeginFrame(rawTimeStamp);
}
void _handleDrawFrame() {
if (_ignoreNextEngineDrawFrame) {
_ignoreNextEngineDrawFrame = false;
return;
}
handleDrawFrame();
}
///主要看下这个方法
void handleDrawFrame() {
assert(_schedulerPhase == SchedulerPhase.midFrameMicrotasks);
Timeline.finishSync(); // end the "Animate" phase
try {
// PERSISTENT FRAME CALLBACKS
_schedulerPhase = SchedulerPhase.persistentCallbacks;
///遍历_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;
Timeline.finishSync(); // end the Frame
assert(() {
if (debugPrintEndFrameBanner)
debugPrint('▀' * _debugBanner!.length);
_debugBanner = null;
return true;
}());
_currentFrameTimeStamp = null;
}
}
void addPersistentFrameCallback(FrameCallback callback) {
_persistentCallbacks.add(callback);
}
mixin RendererBinding on BindingBase, ServicesBinding, SchedulerBinding, GestureBinding, SemanticsBinding, HitTestable {
@override
void initInstances() {
...
addPersistentFrameCallback(_handlePersistentFrameCallback);
...
}
void _handlePersistentFrameCallback(Duration timeStamp) {
drawFrame();
_scheduleMouseTrackerUpdate();
}
}
///widgets/binding.dart
@override
void drawFrame() {
...
try {
if (renderViewElement != null)
///先rebuild, 见3.2
buildOwner.buildScope(renderViewElement);
///后绘制, 见3.3
super.drawFrame();
buildOwner.finalizeTree();
} finally {
assert(() {
debugBuildingDirtyElements = false;
return true;
}());
}
...
}
3.2 刷新build()
void buildScope(Element context, [ VoidCallback callback ]) {
...
while (index < dirtyCount) {
...
_dirtyElements[index].rebuild();
}
...
}
void rebuild() {
...
performRebuild();
}
performRebuild具体执行方法,取决于相应的Element子类,这里以ComponentElement为例
@override
void performRebuild() {
Widget built;
try {
///调用子类的build方法!!!!!!!
built = build();
} catch (e, stack) {
...
} finally {
_dirty = false;
}
try {
_child = updateChild(_child, built, slot);
assert(_child != null);
} catch (e, stack) {
_child = updateChild(null, built, slot);
}
}
3.3 drawFrame (rendering/binding.dart )
@protected
void drawFrame() {
assert(renderView != null);
///更新需要计算其布局的渲染对象,
///在此阶段计算每个渲染对象的大小和位置,
///渲染对象可能会弄脏其绘画或者合成状态,这个过程可能还会调用到build过程。
pipelineOwner.flushLayout();
///pipelineOwne更新具有脏合成位的任何渲染对象,
///在此阶段每个渲染对象都会了解其子项是否需要合成。
///在绘制阶段使用此信息选择如何实现裁剪等视觉效果。
///如果渲染对象有一个自己合成的子项,它需要使用布局信息来创建裁剪,以便将裁剪应用于已合成的子项
pipelineOwner.flushCompositingBits();
///访问需要绘制的任何渲染对象,在此阶段,渲染对象有机会将绘制命令记录到[PictureLayer],并构建其他合成的[Layer];
pipelineOwner.flushPaint();
if (sendFramesToEngine) {
///执行render()将layer树发送给GPU线程
renderView.compositeFrame(); // this sends the bits to the GPU
///编译渲染对象的语义,并将语义发送给操作系统;
pipelineOwner.flushSemantics(); // this also sends the semantics to the OS.
_firstFrameSent = true;
}
}
/// Uploads the composited layer tree to the engine.
///
/// Actually causes the output of the rendering pipeline to appear on screen.
void compositeFrame() {
Timeline.startSync('Compositing', arguments: timelineArgumentsIndicatingLandmarkEvent);
try {
final ui.SceneBuilder builder = ui.SceneBuilder();
final ui.Scene scene = layer!.buildScene(builder);
if (automaticSystemUiAdjustment)
_updateSystemChrome();
_window.render(scene);
scene.dispose();
assert(() {
if (debugRepaintRainbowEnabled || debugRepaintTextRainbowEnabled)
debugCurrentRepaintColor = debugCurrentRepaintColor.withHue((debugCurrentRepaintColor.hue + 2.0) % 360.0);
return true;
}());
} finally {
Timeline.finishSync();
}
}
///window.dart
void render(Scene scene) native 'PlatformConfiguration_render';
4.1 GPU线程
在UI线程执行到compositeFrame()经过多层调用,将渲染任务交给GPU线程来执行. 使用 Skia 库,将 Layer tree进行组合, 生成纹理, 使用 OpenGL 的接口向 GPU 提交渲染内容进行光栅化与合成, 最终显示到屏幕上.