Flutter RendererBinding作用源码分析
<div id="navCategory"><h5 class="catalogue">目录</h5><ul class="first_class_ul"><li>分析</li><li>PipelineOwner</li><ul class="second_class_ul"><li>flushLayout</li><li>flushCompositingBits</li><li>flushPaint</li><li>flushSemantics</li></ul><li>initRenderView</li><ul class="second_class_ul"><li>scheduleInitialLayout</li><li>scheduleInitialPaint</li></ul></ul></div><p class="maodian"></p><h2>分析</h2><div class="cros igoods"><div class="goodsin" data-img="https://img14.360buyimg.com/pop/jfs/t1/116022/23/7439/125020/5ec3466eE7c22dc70/876d770ecad41401.jpg" data-name="Flutter实战指南" data-owner="京东自营" data-price="71.9" data-tgid="38" data-url="https://union-click.jd.com/jdc?e=&p=JF8BAMkJK1olXwUHUlhVD08RCl8IGFwRWAcCVG4ZVxNJXF9RXh5UHw0cSgYYXBcIWDoXSQVJQwYBU1pYCUsXHDZNRwYlIGMAByIAXit1cWwWTgxGOQMYU1sATkcbM2gNHF4dXwMBZF5eDkwXAmoIK2sVXDZQOobrvpOysnPcsdTA1ZEyVW5dD00WCmwBGVsUWwILZF5VDHtUVypcWBhdbTYyV25tOEsnAF9WdVpGVQYBXFheZhZEWTkISAFSMw8FVVdYCksSM20JGlkXbTY"></div></div>
<p>RendererBinding 的作用是负责render tree 和flutter engine之间的连接. 我们在启动App的时候,首先会创建 PiplineOwner ,然后通过platformDispatcher去监听屏幕分辨率变化、系统文字大小变化、亮度、语义等等.最后去初始化RenderView,根据平台去处理如帧回调、鼠标、web之类的信息.</p>
<div class="jb51code"><pre class="brush:cpp;"> void initInstances() {
super.initInstances();
_instance = this;
_pipelineOwner = PipelineOwner(
onNeedVisualUpdate: ensureVisualUpdate,
onSemanticsOwnerCreated: _handleSemanticsOwnerCreated,
onSemanticsOwnerDisposed: _handleSemanticsOwnerDisposed,
);
platformDispatcher
..onMetricsChanged = handleMetricsChanged
..onTextScaleFactorChanged = handleTextScaleFactorChanged
..onPlatformBrightnessChanged = handlePlatformBrightnessChanged
..onSemanticsEnabledChanged = _handleSemanticsEnabledChanged
..onSemanticsAction = _handleSemanticsAction;
initRenderView();
_handleSemanticsEnabledChanged();
assert(renderView != null);
addPersistentFrameCallback(_handlePersistentFrameCallback);
initMouseTracker();
if (kIsWeb) {
addPostFrameCallback(_handleWebFirstFrame);
}
}
</pre></div>
<p class="maodian"></p><h2>PipelineOwner</h2>
<p>这里我们着重讲一下PipelineOwner, 官方描述中有这么一句话The pipeline owner manages the rendering pipeline., 也就是说 PipelineOwner帮我们管理着渲染所需要的. 我们根据PipelineOwner调用的顺序依次讲解下它提供的方法.</p>
<p class="maodian"></p><h3>flushLayout</h3>
<p>这个阶段将计算每个渲染对象的大小和位置, 渲染对象可能会在绘制或者compositing state 的时候被标成dirty,这是什么意思呢? 让我们回归到代码中</p>
<div class="jb51code"><pre class="brush:cpp;">// 持有需要被布局的对象
List<RenderObject> _nodesNeedingLayout = <RenderObject>[];
{
非release包运行代码忽略
...
try {
// 如果当前的节点需要合成
while (_nodesNeedingLayout.isNotEmpty) {
final List<RenderObject> dirtyNodes = _nodesNeedingLayout;
_nodesNeedingLayout = <RenderObject>[];
for (final RenderObject node in dirtyNodes..sort((RenderObject a, RenderObject b) => a.depth - b.depth)) {
if (node._needsLayout && node.owner == this)
node._layoutWithoutResize();
}
}
} finally {
...
}
}
</pre></div>
<p>代码中可以看到, 如果 _nodesNeedingLayout 中对象不为空.说明当前需要被布局,计算其大小.我们可以看到在依次处理节点时,最后一步是执行 _layoutWithoutResize() ,这个方法调用的本质实际上也就是 performLayout(). 那么, performLayout() 做了什么呢? 如果对自定义布局有过了解, 通常我们在实现 performLayout() 的时候.会先去 layout widget . 然后去通过position将widget 定位. 确定好widget在父widget中的相对位置.</p>
<p class="maodian"></p><h3>flushCompositingBits</h3>
<p>这个阶段中, 每个渲染对象都会了解其子对象是否需要合成.在绘制的阶段选择如何实现视觉效果. 这里实际上也就是标记所有的子对象是否需要合成</p>
<div class="jb51code"><pre class="brush:cpp;">void flushCompositingBits() {
...
_nodesNeedingCompositingBitsUpdate.sort((RenderObject a, RenderObject b) => a.depth - b.depth);
for (final RenderObject node in _nodesNeedingCompositingBitsUpdate) {
if (node._needsCompositingBitsUpdate && node.owner == this)
node._updateCompositingBits();
}
_nodesNeedingCompositingBitsUpdate.clear();
...
}
</pre></div>
<p class="maodian"></p><h3>flushPaint</h3>
<p>在这个阶段,我们将会真正的绘制出Layer</p>
<div class="jb51code"><pre class="brush:cpp;">void flushPaint() {
...
try {
final List<RenderObject> dirtyNodes = _nodesNeedingPaint;
_nodesNeedingPaint = <RenderObject>[];
// Sort the dirty nodes in reverse order (deepest first).
for (final RenderObject node in dirtyNodes..sort((RenderObject a, RenderObject b) => b.depth - a.depth)) {
...
if (node._needsPaint && node.owner == this) {
if (node._layerHandle.layer!.attached) {
PaintingContext.repaintCompositedChild(node);
} else {
node._skippedPaintingOnLayer();
}
}
}
...
} finally {
...
}
}
</pre></div>
<p>在绘制的时候将会判断当前的layer是否attached,如果不是attched的状态.则说明当前的layer已经调用detach方法,因此不再需要绘制.所以会跳过绘制,执行 _skippedPaintingOnLayer() 的方法. 如果是attached的状态,则需要调用 repaintCompositedChild() 的方法</p>
<p class="maodian"></p><h3>flushSemantics</h3>
<p>最后,如果启用了语义. 这个阶段将会编译渲染对象的语义,这里就不过多介绍了.</p>
<p class="maodian"></p><h2>initRenderView</h2>
<p>如果说还有比较重要的方法需要讲解, 那么就是 initRenderView() 这个方法了.这里将会创建一个 RenderView的对象作为RenderObject的根 ,同时对它进行初始化.</p>
<div class="jb51code"><pre class="brush:cpp;">void initRenderView() {
renderView = RenderView(configuration: createViewConfiguration(), window: window);
// 准备第一帧启动渲染通道. 这里只会调用一次.
renderView.prepareInitialFrame();
}
</pre></div>
<p>在 PrepareInitalFrame() 中, 我们通过 scheduleInitialLayout和scheduleInitialPaint , 安排微事务队列尽可能快的处理layout和paint.</p>
<p class="maodian"></p><h3>scheduleInitialLayout</h3>
<p>在这个阶段,主要是将owner的_nodesNeedingLayout 对象中加入这个初始化的renderview.</p>
<p class="maodian"></p><h3>scheduleInitialPaint</h3>
<p>这个阶段中, 我们将_layerHandle 中的layer 赋值成当前layer.并在owner中加入 _nodesNeedingPaint .</p>
<div class="jb51code"><pre class="brush:cpp;">void scheduleInitialPaint(ContainerLayer rootLayer) {
_layerHandle.layer = rootLayer;
owner!._nodesNeedingPaint.add(this);
}
</pre></div>
<p>今天的RendererBinding源码分析就暂告一个段落了,它主要是负责了测量布局、绘制之类的方法. 作为一个入口还是有了解的必要的, 建议大家有时间可以多看看.</p>
<p>以上就是Flutter RendererBinding作用源码分析的详细内容,更多关于Flutter RendererBinding的资料请关注琼殿技术社区其它相关文章!</p>
<div class="art_xg">
<b>您可能感兴趣的文章:</b><ul><li>Flutter实现手势识别功能详解方法</li><li>基于Flutter实现手势密码加密与解锁功能</li><li>Flutter手势密码的实现示例(附demo)</li><li>Flutter框架解决盒约束widget和assets里加载资产技术</li><li>flutter消息推送客户端集成方案详解</li><li>Flutter图片缓存管理ImageCache原理分析</li><li>Flutter项目手势运用及单独指针消歧问题解决方案</li></ul>
</div>
</div>
<!--endmain-->
頁:
[1]