一尘不染

了解Flutter渲染引擎

flutter

该文档在这里了解如何更新ListView说:

在Flutter中,如果要更新setState()中的小部件列表,您将很快看到数据在视觉上没有改变。这是因为调用setState()时,Flutter呈现引擎将查看小部件树以查看是否有任何更改。到达ListView时,它将执行==检查,并确定两个ListView是相同的。没有任何更改,因此不需要更新。

作为更新ListView的简单方法,请在setState()内创建一个新List,然后将数据从旧列表复制到新列表。

在这种情况下,我不了解渲染引擎如何确定小部件树中是否有任何更改。

在AFAICS中,我们关心调用setState,它将State对象标记为脏并要求其重建。一旦重建,就会有一个新的ListView,不是吗?那么,==支票为什么说是同一对象呢?

此外,新的List将是内部的State对象,不颤振引擎比较里面的所有对象State的对象?我以为它只比较Widget树。

因此,基本上,我不了解渲染引擎如何决定要更新的内容以及要忽略的内容,因为我看不到创建新内容如何List将任何信息发送到渲染引擎,正如文档所说的那样,渲染引擎只是寻找新的ListView…而AFAIK新的List不会创建新的ListView


阅读 369

收藏
2020-08-13

共1个答案

一尘不染

Flutter不仅由Widget组成

调用时setState,将 Widget 标记为脏。但是,此小部件实际上并不是您在屏幕上渲染的。存在用于创建/
更改RenderObject的小部件;这些RenderObjects在屏幕上绘制内容。

RenderObject和Widget之间的链接是使用一种新型的Widget完成的:RenderObjectWidget(例如LeafRenderObjectWidget

Flutter提供的大多数小部件在某种程度上都是RenderObjectWidget,包括ListView。

一个典型的RenderObjectWidget示例是这样的:

class MyWidget extends LeafRenderObjectWidget {
  final String title;

  MyWidget(this.title);

  @override
  MyRenderObject createRenderObject(BuildContext context) {
    return new MyRenderObject()
      ..title = title;
  }

  @override
    void updateRenderObject(BuildContext context, MyRenderObject renderObject) {
      renderObject
        ..title = title;
    }
}

本示例使用小部件创建/更新RenderObject。仅仅通知框架还有一些东西需要重画。

要进行RenderObject重绘,必须调用markNeedsPaintmarkNeedsLayout在所需的renderObject上进行。

通常这是由RenderObject本身使用自定义字段设置器通过以下方式完成的:

class MyRenderObject extends RenderBox {
  String _title;
  String get title => _title;
  set title(String value) {
    if (value != _title) {
      markNeedsLayout();
      _title = value;
    }
  }
}

请注意if (value != previous)

此检查可确保在不更改任何内容的情况下重建窗口小部件时,Flutter不会重新布局/重新绘制任何内容。

正是由于这种确切的条件,突变ListMap没有重新ListView渲染。它基本上具有以下内容:

List<Widget> _children;
List<Widget> get children => _children;
set children(List<Widget> value) {
  if (value != _children) {
    markNeedsLayout();
    _children = value;
  }
}

但它意味着,如果 发生变异 的名单,而不是创建一个新的,在渲染对象不会被标记为需要重新布局/重绘。因此,将不会有任何视觉更新。

2020-08-13