美文网首页
Flutter setState为什么不会造成性能困扰?

Flutter setState为什么不会造成性能困扰?

作者: mtko | 来源:发表于2020-04-10 17:22 被阅读0次

    setState为什么不会造成性能困扰?
    因为只更新当前图层树。

    flutter是怎么做element diff,做到只布局、绘制、合成差异部分视图的?
    见以下代码

    核心代码

    Flutter版本

    Flutter: 1.12.13+hotfix.8
    

    核心类

    abstract class RenderObject
    

    widget层调用

    setState();
    

    核心数据结构

    链表
    

    遍历链表寻找relayout boundary,重新布局

    void markNeedsLayout() {
        assert(_debugCanPerformMutations);
        if (_needsLayout) {
          assert(_debugSubtreeRelayoutRootAlreadyMarkedNeedsLayout());
          return;
        }
        assert(_relayoutBoundary != null);
        if (_relayoutBoundary != this) {
          markParentNeedsLayout();
        } else {
          _needsLayout = true;
          if (owner != null) {
            assert(() {
              if (debugPrintMarkNeedsLayoutStacks)
                debugPrintStack(label: 'markNeedsLayout() called for $this');
              return true;
            }());
            owner._nodesNeedingLayout.add(this);
            owner.requestVisualUpdate();
          }
        }
      }
    

    遍历链表检查renderObject是否是重绘边界(isRepaintBoundary = true)时,决定合成范围

    void markNeedsCompositingBitsUpdate() {
        if (_needsCompositingBitsUpdate)
          return;
        _needsCompositingBitsUpdate = true;
        if (parent is RenderObject) {
          final RenderObject parent = this.parent;
          if (parent._needsCompositingBitsUpdate)
            return;
          if (!isRepaintBoundary && !parent.isRepaintBoundary) {
            parent.markNeedsCompositingBitsUpdate();
            return;
          }
        }
        assert(() {
          final AbstractNode parent = this.parent;
          if (parent is RenderObject)
            return parent._needsCompositing;
          return true;
        }());
        // parent is fine (or there isn't one), but we are dirty
        if (owner != null)
          owner._nodesNeedingCompositingBitsUpdate.add(this);
      }
    

    遍历链表检查renderObject是否是重绘边界(isRepaintBoundary = true),决定绘制范围,或 没有标记isRepaintBoundary的RenderObject时全部绘制

    void markNeedsPaint() {
        assert(owner == null || !owner.debugDoingPaint);
        if (_needsPaint)
          return;
        _needsPaint = true;
        if (isRepaintBoundary) {
          assert(() {
            if (debugPrintMarkNeedsPaintStacks)
              debugPrintStack(label: 'markNeedsPaint() called for $this');
            return true;
          }());
          // If we always have our own layer, then we can just repaint
          // ourselves without involving any other nodes.
          assert(_layer is OffsetLayer);
          if (owner != null) {
            owner._nodesNeedingPaint.add(this);
            owner.requestVisualUpdate();
          }
        } else if (parent is RenderObject) {
          final RenderObject parent = this.parent;
          parent.markNeedsPaint();
          assert(parent == this.parent);
        } else {
          assert(() {
            if (debugPrintMarkNeedsPaintStacks)
              debugPrintStack(label: 'markNeedsPaint() called for $this (root of render tree)');
            return true;
          }());
          // If we're the root of the render tree (probably a RenderView),
          // then we have to paint ourselves, since nobody else can paint
          // us. We don't add ourselves to _nodesNeedingPaint in this
          // case, because the root is always told to paint regardless.
          if (owner != null)
            owner.requestVisualUpdate();
        }
      }
    

    结语:

    1.setState的节点越远离根部,布局、合成、绘制的开销越少
    2.重写isRepaintBoundary可变化绘制范围,可影响开销;如使用RepaintBoundary部件
    3.绝对宽高可减少开销(constraints.isTight)

    RenderObject relayoutBoundary;
        if (!parentUsesSize || sizedByParent || constraints.isTight || parent is! RenderObject) {
          relayoutBoundary = this;
        } else {
          final RenderObject parent = this.parent;
          relayoutBoundary = parent._relayoutBoundary;
        }
    

    相关文章

      网友评论

          本文标题:Flutter setState为什么不会造成性能困扰?

          本文链接:https://www.haomeiwen.com/subject/qjjrmhtx.html