Flutter renderObject 的更新相关

301 阅读2分钟

开始

从Element.updateChild开始.这里先不看创建等其他过程.

Element updateChild(Element child, Widget newWidget, dynamic newSlot) {
  ...
  child.update(newWidget);
  newChild = child;
  ...
  return newChild;
  }

RenderObjectElement.update

RenderObjectElement它有一个自己实现的update,它这里就是调用了RenderObjectWidget的updateRenderObject方法.

@override
  void update(covariant RenderObjectWidget newWidget) {
    super.update(newWidget);
    widget.updateRenderObject(this, renderObject);
    _dirty = false;
}

其实RenderObejctElement的子类还有自己实现的update方法,但是一般都是继续更新子组件,所以这里暂不多说.

Padding.updateRenderObject

看源码我们可以发现RenderObjectWidget的updateRenderObject是一个空方法,这里我们直接看子类的实现,我们这里以Padding举例.

@override
void updateRenderObject(BuildContext context, RenderPadding renderObject) {
    renderObject
    ///这里会调用RenderPadding的padding set方法.
      ..padding = padding
      ..textDirection = Directionality.of(context);
}


RenderPadding.padding

///RenderPadding.padding
set padding(EdgeInsetsGeometry value) {
  ///这里它做了一个优化,如果,更新的padding和当前的padding相同则不更新.
  if (_padding == value)
    return;
  _padding = value;
  ///这里会标记需要更新.
  _markNeedResolution();
}

RenderPadding._markNeedResolution

void _markNeedResolution() {
  _resolvedPadding = null;
  ///这里标记当前这个renderObject是需要重新layout的.
  markNeedsLayout();
}

RenderObject.markNeedsLayout

void markNeedsLayout() {
  ///如果已标记为需要更新则退出.
  if (_needsLayout) {
    return;
  }
  ///如果当前renderObject并不是_relayoutBoundary则调用父组件的markNeedsLayout
  ///递归到满足条件为止
  if (_relayoutBoundary != this) {
    markParentNeedsLayout();
  } else {
    _needsLayout = true;
    if (owner != null) {
      ///将当前RenderObject添加到需要重新 layout的数组中
      owner._nodesNeedingLayout.add(this);
      owner.requestVisualUpdate();
    }
  }
}

PipelineOwner.flushLayout

void flushLayout() {
  if (!kReleaseMode) {
    Timeline.startSync('Layout', arguments: timelineArgumentsIndicatingLandmarkEvent);
  }
  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 {
    if (!kReleaseMode) {
      Timeline.finishSync();
    }
  }
}

RenderObject._layoutWithoutResize

void _layoutWithoutResize() {
  RenderObject debugPreviousActiveLayout;
  try {
    /// 这里的performLayout方法RenderObject和RenderBox都没有实现,我们这里看一下RenderPadding实现的方法.
    performLayout();
    markNeedsSemanticsUpdate();
  } catch (e, stack) {
    _debugReportException('performLayout', e, stack);
  }
  _needsLayout = false;
  /// 这里会在performLayout之后调用
  markNeedsPaint();
}

RenderPadding.performLayout

@override
void performLayout() {
  final BoxConstraints constraints = this.constraints;
  _resolve();
  if (child == null) {
    size = constraints.constrain(Size(
      _resolvedPadding.left + _resolvedPadding.right,
      _resolvedPadding.top + _resolvedPadding.bottom,
    ));
    return;
  }
  final BoxConstraints innerConstraints = constraints.deflate(_resolvedPadding);
  ///给子节点的大小约束.
  child.layout(innerConstraints, parentUsesSize: true);
  final BoxParentData childParentData = child.parentData as BoxParentData;
  ///控制子组件在父组件的位置.
  childParentData.offset = Offset(_resolvedPadding.left, _resolvedPadding.top);
  ///当前widget的size大小,这里的size就是Padding的size
  size = constraints.constrain(Size(
    _resolvedPadding.left + child.size.width + _resolvedPadding.right,
    _resolvedPadding.top + child.size.height + _resolvedPadding.bottom,
  ));
}

RenderObject.markNeedsPaint

void markNeedsPaint() {
  if (_needsPaint)
    return;
  ///标记需要重新paint
  _needsPaint = true;
  ///如果RenderObject.isRepaintBoundary为true,则该RenderObject拥有layer,直接绘制
  if (isRepaintBoundary) {
    if (owner != null) {
      ///找到最近的layer,绘制
      owner._nodesNeedingPaint.add(this);
      owner.requestVisualUpdate();
    }
  } else if (parent is RenderObject) {
    ///没有自己的layer,会和祖先节点共用一个layer
    final RenderObject parent = this.parent as RenderObject;
    ///向父级递归查找.
    parent.markNeedsPaint();
  } else {
    if (owner != null)
      owner.requestVisualUpdate();
  }
}

PipelineOwner.flushPaint

void flushPaint() {
  if (!kReleaseMode) {
    Timeline.startSync('Paint', arguments: timelineArgumentsIndicatingLandmarkEvent);
  }
  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._layer.attached) {
          ///真正的绘制逻辑
          PaintingContext.repaintCompositedChild(node);
        } else {
          node._skippedPaintingOnLayer();
        }
      }
    }
  } finally {
    if (!kReleaseMode) {
      Timeline.finishSync();
    }
  }
}

到这里就差不过更新结束了.