首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >了解颤振渲染引擎

了解颤振渲染引擎
EN

Stack Overflow用户
提问于 2018-11-25 13:30:26
回答 1查看 5.2K关注 0票数 17

关于如何更新这里的docs ListView说:

如果您要更新setState()中的小部件列表,那么您很快就会看到数据没有在视觉上发生变化。这是因为当调用setState()时,颤振呈现引擎会查看小部件树,以查看是否有任何变化。当它到达您的ListView时,它执行一个==检查,并确定两个ListViews是相同的。什么都没有改变,所以不需要更新。 对于更新ListView的简单方法,请在setState()中创建一个新列表,并将数据从旧列表复制到新列表中。

在本例中,我不知道呈现引擎如何确定Widget中是否有任何更改。

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

另外,新的List将是State对象的内部,颤振引擎会比较State对象中的所有对象吗?我以为它只是比较了Widget树。

所以,基本上我不明白渲染引擎是如何决定它要更新什么以及忽略什么,因为我看不出创建一个新的List是如何向呈现引擎发送任何信息的,因为文档说渲染引擎只是在寻找一个新的ListView.而AFAIK一个新的List不会创建一个新的ListView

EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2018-11-25 14:17:36

颤振不仅是由窗口小部件制成的。

调用setState时,可以将Widget标记为脏。但是这个Widget实际上不是你在屏幕上呈现的东西。小部件存在以创建/变异RenderObjects;正是这些RenderObjects在屏幕上绘制内容。

RenderObjects和小部件之间的链接是使用一种新的Widget:RenderObjectWidget (如LeafRenderObjectWidget)完成的。

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

一个典型的RenderObjectWidget示例是:

代码语言:javascript
复制
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上调用markNeedsPaintmarkNeedsLayout

这通常由RenderObject自己使用自定义字段设置器这样完成:

代码语言:javascript
复制
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重发。它基本上有以下几点:

代码语言:javascript
复制
List<Widget> _children;
List<Widget> get children => _children;
set children(List<Widget> value) {
  if (value != _children) {
    markNeedsLayout();
    _children = value;
  }
}

但这意味着,如果您更改列表而不是创建新列表,则不会将RenderObject标记为需要中继/重新绘制。因此不会有任何视觉更新。

票数 40
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/53467979

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档