关于如何更新这里的docs ListView说:
如果您要更新setState()中的小部件列表,那么您很快就会看到数据没有在视觉上发生变化。这是因为当调用setState()时,颤振呈现引擎会查看小部件树,以查看是否有任何变化。当它到达您的ListView时,它执行一个==检查,并确定两个ListViews是相同的。什么都没有改变,所以不需要更新。 对于更新ListView的简单方法,请在setState()中创建一个新列表,并将数据从旧列表复制到新列表中。
在本例中,我不知道呈现引擎如何确定Widget中是否有任何更改。
AFAICS,我们关心调用setState,它将State对象标记为脏,并要求它重新构建。一旦它重新构建,就会有一个新的ListView,不是吗?那么为什么==检查说它是同一个对象呢?
另外,新的List将是State对象的内部,颤振引擎会比较State对象中的所有对象吗?我以为它只是比较了Widget树。
所以,基本上我不明白渲染引擎是如何决定它要更新什么以及忽略什么,因为我看不出创建一个新的List是如何向呈现引擎发送任何信息的,因为文档说渲染引擎只是在寻找一个新的ListView.而AFAIK一个新的List不会创建一个新的ListView。
发布于 2018-11-25 14:17:36
颤振不仅是由窗口小部件制成的。
调用setState时,可以将Widget标记为脏。但是这个Widget实际上不是你在屏幕上呈现的东西。小部件存在以创建/变异RenderObjects;正是这些RenderObjects在屏幕上绘制内容。
RenderObjects和小部件之间的链接是使用一种新的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,必须在所需的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)。
此检查确保当小部件重新构建而不更改任何内容时,Flutter不会中继/重新绘制任何内容。
正是由于这种确切的情况,变异List或Map并不会使ListView重发。它基本上有以下几点:
List<Widget> _children;
List<Widget> get children => _children;
set children(List<Widget> value) {
if (value != _children) {
markNeedsLayout();
_children = value;
}
}但这意味着,如果您更改列表而不是创建新列表,则不会将RenderObject标记为需要中继/重新绘制。因此不会有任何视觉更新。
https://stackoverflow.com/questions/53467979
复制相似问题