了解Flutter渲染引擎 [英] Understanding Flutter Render Engine

查看:155
本文介绍了了解Flutter渲染引擎的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

文档 关于如何更新ListView说:

在Flutter中,如果要更新 setState(),您将很快看到您的数据没有更改 视觉上.这是因为当调用setState()时,Flutter 渲染引擎查看小部件树以查看是否有任何东西 改变了.当到达ListView时,它将执行==检查,然后 确定两个ListView相同.什么也没有变, 因此不需要更新.

In Flutter, if you were to update the list of widgets inside a setState(), you would quickly see that your data did not change visually. This is because when setState() is called, the Flutter rendering engine looks at the widget tree to see if anything has changed. When it gets to your ListView, it performs a == check, and determines that the two ListViews are the same. Nothing has changed, so no update is required.

对于更新ListView的简单方法,请在其中创建一个新List setState(),然后将数据从旧列表复制到新列表.

For a simple way to update your ListView, create a new List inside of setState(), and copy the data from the old list to the new list.

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

I don't get how the Render Engine determines if there are any changes in the Widget Tree in this case.

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

AFAICS, we care calling setState, which marks the State object as dirty and asks it to rebuild. Once it rebuilds there will be a new ListView, won't it? So how come the == check says it's the same object?

此外,新的List将位于State对象的内部,Flutter引擎是否会比较State对象内部的所有对象?我以为它只比较了Widget树.

Also, the new List will be internal to the State object, does the Flutter engine compare all the objects inside the State object? I thought it only compared the Widget tree.

因此,基本上,我不了解渲染引擎如何决定要更新的内容以及要忽略的内容,因为我看不到创建新的List如何将任何信息发送到渲染引擎,因为docs表示,渲染引擎只是在寻找新的ListView ...,而AFAIK会在新的List中创建新的ListView.

So, basically I don't understand how the Render Engine decides what it's going to update and what's going to ignore, since I can't see how creating a new List sends any information to the Render Engine, as the docs says the Render Engine just looks for a new ListView... And AFAIK a new List won't create a new ListView.

推荐答案

Flutter并非仅由窗口小部件.

Flutter isn't made only of Widgets.

呼叫setState时,将小部件标记为脏.但是,该小部件实际上并不是您在屏幕上渲染的. 存在用于创建/更改 RenderObjects 的小部件.正是这些RenderObjects在屏幕上绘制了您的内容.

When you call setState, you mark the Widget as dirty. But this Widget isn't actually what you render on the screen. Widgets exist to create/mutate RenderObjects; it's these RenderObjects that draw your content on the screen.

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

The link between RenderObjects and Widgets is done using a new kind of Widget: RenderObjectWidget (such as LeafRenderObjectWidget)

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

Most widgets provided by Flutter are to some extent a RenderObjectWidget, including ListView.

一个典型的RenderObjectWidget示例为:

A typical RenderObjectWidget example would be this:

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.仅仅通知框架有一些需要重画的内容是不够的.

This example uses a widget to create/update a RenderObject. It's not enough to notify the framework that there's something to repaint though.

要重新渲染RenderObject,必须在所需的renderObject上调用markNeedsPaintmarkNeedsLayout.

To make a RenderObject repaint, one must call markNeedsPaint or markNeedsLayout on the desired renderObject.

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

This is usually done by the RenderObject itself using custom field setter this way:

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

注意if (value != previous).

此检查可确保在不更改任何内容的情况下重建窗口小部件时,Flutter不会中继/重绘任何内容.

This check ensures that when a widget rebuilds without changing anything, Flutter doesn't relayout/repaint anything.

正是由于这种确切条件,对ListMap进行突变不会使ListView重新呈现.它基本上具有以下内容:

It's due to this exact condition that mutating List or Map doesn't make ListView rerender. It basically has the following:

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

但是这意味着,如果您对列表进行变异而不是创建一个新列表,则RenderObject不会被标记为需要重新布局/重新绘制.因此,不会进行任何视觉更新.

But it implies that if you mutate the list instead of creating a new one, the RenderObject will not be marked as needing a relayout/repaint. Therefore there won't be any visual update.

这篇关于了解Flutter渲染引擎的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆