该文档在这里了解如何更新ListView说:
ListView
在Flutter中,如果要更新setState()中的小部件列表,您将很快看到数据在视觉上没有改变。这是因为调用setState()时,Flutter呈现引擎将查看小部件树以查看是否有任何更改。到达ListView时,它将执行==检查,并确定两个ListView是相同的。没有任何更改,因此不需要更新。 作为更新ListView的简单方法,请在setState()内创建一个新List,然后将数据从旧列表复制到新列表。
在Flutter中,如果要更新setState()中的小部件列表,您将很快看到数据在视觉上没有改变。这是因为调用setState()时,Flutter呈现引擎将查看小部件树以查看是否有任何更改。到达ListView时,它将执行==检查,并确定两个ListView是相同的。没有任何更改,因此不需要更新。
作为更新ListView的简单方法,请在setState()内创建一个新List,然后将数据从旧列表复制到新列表。
在这种情况下,我不了解渲染引擎如何确定小部件树中是否有任何更改。
在AFAICS中,我们关心调用setState,它将State对象标记为脏并要求其重建。一旦重建,就会有一个新的ListView,不是吗?那么,==支票为什么说是同一对象呢?
setState
State
==
此外,新的List将是内部的State对象,不颤振引擎比较里面的所有对象State的对象?我以为它只比较Widget树。
List
Widget
因此,基本上,我不了解渲染引擎如何决定要更新的内容以及要忽略的内容,因为我看不到创建新内容如何List将任何信息发送到渲染引擎,正如文档所说的那样,渲染引擎只是寻找新的ListView…而AFAIK新的List不会创建新的ListView。
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重绘,必须调用markNeedsPaint或markNeedsLayout在所需的renderObject上进行。
markNeedsPaint
markNeedsLayout
通常这是由RenderObject本身使用自定义字段设置器通过以下方式完成的:
class MyRenderObject extends RenderBox { String _title; String get title => _title; set title(String value) { if (value != _title) { markNeedsLayout(); _title = value; } } }
请注意if (value != previous)。
if (value != previous)
此检查可确保在不更改任何内容的情况下重建窗口小部件时,Flutter不会重新布局/重新绘制任何内容。
正是由于这种确切的条件,突变List或Map没有重新ListView渲染。它基本上具有以下内容:
Map
List<Widget> _children; List<Widget> get children => _children; set children(List<Widget> value) { if (value != _children) { markNeedsLayout(); _children = value; } }
但它意味着,如果 发生变异 的名单,而不是创建一个新的,在渲染对象不会被标记为需要重新布局/重绘。因此,将不会有任何视觉更新。