//绘制过程概述:在绘制过程中,渲染树会生成一个合成层树,这些层被上传到引擎并由合成器显示。 //Layer 是合成层树的一个切片,layer被排列成层次结构,每个节点都可能影响它下面的节点 在绘制的时候,会把每个绘制节点保存到Layer上面, //最后合成树,创建一个SceneBuilder对象,根layer对象调用addToScene方法,SceneBuilder.build以获得一个Scene。然后可以使用dart:ui.FlutterView.render绘制场景。 RendererBinding
@protected void 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; } }
看回顾 flutter Widget、Element和RenderObject 树的插入源码分析 RenderView 插入树过程 void prepareInitialFrame() { scheduleInitialPaint(_updateMatricesAndCreateNewRootLayer()); ...省略 }
TransformLayer _updateMatricesAndCreateNewRootLayer() { _rootTransform = configuration.toMatrix(); //创建根layer final TransformLayer rootLayer = TransformLayer(transform: _rootTransform); //绑定渲染对象 rootLayer.attach(this); return rootLayer; }
void scheduleInitialPaint(ContainerLayer rootLayer) { _layerHandle.layer = rootLayer; //添加自己到绘制节点 这里是根节点 owner!._nodesNeedingPaint.add(this); } 绘制 PipelineOwner void flushPaint() { final ListdirtyNodes = _nodesNeedingPaint; _nodesNeedingPaint = []; 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(); } } } }
PaintingContextstatic void _repaintCompositedChild( RenderObject child, { bool debugAlsoPaintedParent = false, PaintingContext? childContext, }) { //获取当前layer OffsetLayer? childLayer = child._layerHandle.layer as OffsetLayer?; //创建新的 if (childLayer == null) { final OffsetLayer layer = OffsetLayer(); child._layerHandle.layer = childLayer = layer; } else { //否则清空子layer childLayer.removeAllChildren(); } //RenderObject不是直接持有画布,而是使用PaintingContext进行绘画。PaintingContext有一个Canvas,它接收单独的绘制 *** 作,并且还具有绘制子渲染对象的功能。 childContext ??= PaintingContext(childLayer, child.paintBounds); child._paintWithContext(childContext, Offset.zero); childContext.stopRecordingIfNeeded(); } RenderObject void _paintWithContext(PaintingContext context, Offset offset) { //layout 时候已经为false.回顾请看 flutter widget layout测量源码解析 if (_needsLayout) return; //标记 _needsPaint = false; try { //开始绘制 paint(context, offset); } ...省略 }
RenderView
@override void paint(PaintingContext context, Offset offset) { if (child != null) //子对象依次递归 context.paintChild(child!, offset); }
PaintingContext
void paintChild(RenderObject child, Offset offset) { //以RepaintBoundary 为例 子部件是边界 if (child.isRepaintBoundary) { //停止录制, 把当前的 canvas 等值置为空 stopRecordingIfNeeded(); _compositeChild(child, offset); } else { child._paintWithContext(this, offset); } }
//子部件不是边界的情况下
void _paintWithContext(PaintingContext context, Offset offset) { if (_needsLayout) return; _needsPaint = false; try { //开始绘制 paint(context, offset); } }
//子部件是边界的情况下
void _compositeChild(RenderObject child, Offset offset) { // 以RepaitBoundary 为例 if (child._needsPaint) { //再次递归回到_repaintCompositedChild repaintCompositedChild(child, debugAlsoPaintedParent: true); } //获取边界的layer final OffsetLayer childOffsetLayer = child._layerHandle .layer! as OffsetLayer; childOffsetLayer.offset = offset; //添加子layer appendLayer(childOffsetLayer); }
@protected void appendLayer(Layer layer) { /删除当前对象在父类的引用 layer.remove(); //插入 _containerLayer.append(layer); }
@override void adoptChild(AbstractNode child) { //是否禁用渲染的保留 if (!alwaysNeedsAddToScene) { markNeedsAddToScene(); } super.adoptChild(child); }
AbstractNode
void adoptChild(covariant AbstractNode child) { //绑定当前layer child._parent = this; if (attached) //子layer绑定根的渲染对象 保证子对象都拥有同一个owner child.attach(_owner!); //深度加一 redepthChild(child); }
再来看 markNeedsPaint
layout 测量的时候标记
RenderObject
void markNeedsPaint() { if (_needsPaint) return; _needsPaint = true; if (isRepaintBoundary) { if (owner != null) { //是边界,就添加进去 owner!._nodesNeedingPaint.add(this); //请求更新 owner!.requestVisualUpdate(); } } else if (parent is RenderObject) { final RenderObject parent = this.parent! as RenderObject; //递归调用父类,直到边界 parent.markNeedsPaint(); } else { //直接请求刷新 if (owner != null) owner!.requestVisualUpdate(); } }
具体paint 实现 ColoredBox 为例
@override void paint(PaintingContext context, Offset offset) { if (size > Size.zero) { //开始绘制 context.canvas.drawRect(offset & size, Paint()..color = color); } if (child != null) { context.paintChild(child!, offset); } }
@override Canvas get canvas { if (_canvas == null) _startRecording(); return _canvas!; } void _startRecording() { //绘制保存的地方 _currentLayer = PictureLayer(estimatedBounds); _recorder = ui.PictureRecorder(); //绘制的画布 _canvas = Canvas(_recorder!); //绘制的layer 保存到父layer下面 _containerLayer.append(_currentLayer!); }
//setstate 重绘时候 *** 作
void setState(VoidCallback fn) { ...省略 _element!.markNeedsBuild(); }
void markNeedsBuild() { if (_lifecycleState != _ElementLifecycle.active) return; if (dirty) return; //标记 _dirty = true; //添加标记元素脏, 在重建 owner!.scheduleBuildFor(this); }
欢迎分享,转载请注明来源:内存溢出
评论列表(0条)