markNeedsBuild()方法是通知Flutter引擎需要重新构建widget树,而Flutter引擎会在Native层发送命令,通知Native层需要刷新Flutter视图。Native层收到命令后,会调用Flutter引擎提供的接口来刷新Flutter视图,并将新的Flutter视图与Native视图合并后显示在屏幕上。
1、flutter标记需要刷新-》flutter 通知native刷新-〉native调用flutter刷新
setState(() { });
void setState(VoidCallback fn) {
assert(fn != null);
final Oject? result = fn() as dynamic;
_element!.markNeedsBuild();
}
_element!.markNeedsBuild();
void markNeedsBuild() {
assert(_lifecycleState != _ElementLifecycle.defunct);
if (_lifecycleState != _ElementLifecycle.active)
return;
assert(owner != null);
assert(_lifecycleState == _ElementLifecycle.active);
if (dirty)
return;
_dirty = true;
owner!.scheduleBuildFor(this);
}
owner!.scheduleBuildFor(this);
onBuildScheduled!();
_dirtyElements.add(element);
void scheduleBuildFor(Element element) {
assert(element != null);
assert(element.owner == this);
if (element._inDirtyList) {
_dirtyElementsNeedsResorting = true;
return;
}
if (!_scheduledFlushDirtyElements && onBuildScheduled != null) {
_scheduledFlushDirtyElements = true;
onBuildScheduled!();
}
_dirtyElements.add(element);
element._inDirtyList = true;
}
onBuildScheduled!();
void scheduleFrame() {
if (_hasScheduledFrame || !framesEnabled)
return;
ensureFrameCallbacksRegistered();
platformDispatcher.scheduleFrame();
_hasScheduledFrame = true;
}
platformDispatcher.scheduleFrame();:
ui.PlatformDispatcher get platformDispatcher => ui.PlatformDispatcher.instance;
2、native 调用flutter 刷新
flutter 刷新界面
native通知到flutter,flutter回调:
PlatformDispatcher.instance._drawFrame();
@pragma('vm:entry-point')
void _drawFrame() {
PlatformDispatcher.instance._drawFrame();
}
void drawFrame()
mixin WidgetsBinding
void drawFrame() {
try {
if (renderViewElement != null)
buildOwner!.buildScope(renderViewElement!);
super.drawFrame();
buildOwner!.finalizeTree();
} finally {
}
}
buildOwner!.buildScope(renderViewElement!);树:
这里面完成widget、element、renderboject 树 创建和更新。
mixin WidgetsBinding {
_buildOwner = BuildOwner();
}
class BuildOwner {
void buildScope(Element context, [ VoidCallback? callback ])
}
RendererBinding drawFrame();
super.drawFrame();
void drawFrame() {
assert(renderView != null);
pipelineOwner.flushLayout(); //调用管道所有者的flushLayout方法,以刷新布局。在Flutter中,布局是指定义小部件如何排列的过程。
pipelineOwner.flushCompositingBits(); //调用管道所有者的flushCompositingBits方法,以刷新合成位。合成是指在渲染过程中,将小部件组合成一个图像的过程。
pipelineOwner.flushPaint(); //调用管道所有者的flushPaint方法,以刷新绘制。在Flutter中,绘制是指将小部件渲染为像素的过程。
if (sendFramesToEngine) {
renderView.compositeFrame(); // this sends the bits to the GPU,调用渲染视图的compositeFrame方法,将渲染帧发送到GPU
pipelineOwner.flushSemantics(); // this also sends the semantics to the OS.用管道所有者的flushSemantics方法,将语义信息发送到操作系统。在Flutter中,语义信息用于描述小部件在用户界面中的作用。
_firstFrameSent = true;//将_firstFrameSent变量设置为true,以表示第一帧已经发送到GPU。
}
}
《Flutter实战·第二版》布局(Layout)过程 链接地址:
Layout(布局)过程主要是确定每一个组件的布局信息(大小和位置),Flutter 的布局过程如下:
- 父节点向子节点传递约束(constraints)信息,限制子节点的最大和最小宽高。
- 子节点根据约束信息确定自己的大小(size)。
- 父节点根据特定布局规则(不同布局组件会有不同的布局算法)确定每一个子节点在父节点布局空间中的位置,用偏移 offset 表示。
- 递归整个过程,确定出每一个节点的大小和位置。
可以看到,组件的大小是由自身决定的,而组件的位置是由父组件决定的。
网友评论