StatefulWidget的性能注意事项

Performance considerations-性能注意事项

There are two primary categories of StatefulWidgets.
StatefulWidget 有两个主要类别。

The first is one which allocates resources in State.initState and disposes of them in State.dispose, but which does not depend on InheritedWidgets or call State.setState. Such widgets are commonly used at the root of an application or page, and communicate with subwidgets via ChangeNotifiers, Streams, or other such objects. Stateful widgets following such a pattern are relatively cheap (in terms of CPU and GPU cycles), because they are built once then never update. They can, therefore, have somewhat complicated and deep build methods.
第一个是在 State.initState 中分配资源并在 State.dispose 中dispose它们,但它不依赖于 InheritedWidgets 或调用 State.setState。 此类Widget通常用于App或页面的root层级,并通过 ChangeNotifiers、Streams 或其他此类对象与子Widget进行通信。 遵循这种模式的StatefulWidget相对轻量(就 CPU 和 GPU 周期而言),因为它们只需build一次后就不会更新。 因此,它们可以有一些复杂而深入的build方法。

The second category is widgets that use State.setState or depend on InheritedWidgets. These will typically rebuild many times during the application’s lifetime, and it is therefore important to minimize the impact of rebuilding such a widget. (They may also use State.initState or State.didChangeDependencies and allocate resources, but the important part is that they rebuild.)
第二类是使用 State.setState 或依赖于 InheritedWidgets 的Widget。 这些通常会在App的生命周期内多次rebuild,因此尽量减少rebuild此类Widget的影响非常重要。 (他们也可能使用 State.initState 或State.didChangeDependencies 并分配资源,但关键点是他们的rebuild。)

There are several techniques one can use to minimize the impact of rebuilding a stateful widget:
有几种技术可以用来最小化StatefulWidget的rebuild影响:

  1. Push the state to the leaves. For example, if your page has a ticking clock, rather than putting the state at the top of the page and rebuilding the entire page each time the clock ticks, create a dedicated clock widget that only updates itself.
    将state放置到到(widget 树)叶子上。 例如,如果你的页面有一个tick时钟,请不要将state放在页面顶部,否则每次时钟tick时整个页面都会rebuild,而是创建一个专门处理时钟,仅更新自身部分的Widget。

  2. Minimize the number of nodes transitively created by the build method and any widgets it creates. Ideally, a stateful widget would only create a single widget, and that widget would be a RenderObjectWidget. (Obviously this isn’t always practical, but the closer a widget gets to this ideal, the more efficient it will be.)
    尽可能减少由 build 方法创建的Widget继续创建的Widget节点的数量。 理想情况下,StatefulWidget只会创建一个Widget,并且该Widget将是 RenderObjectWidget。 (显然这并不总是实用的,但Widget越接近这个理想,它的效率就越高。)

  3. If a subtree does not change, cache the widget that represents that subtree and re-use it each time it can be used. It is massively more efficient for a widget to be re-used than for a new (but identically-configured) widget to be created. Factoring out the stateful part into a widget that takes a child argument is a common way of doing this.
    如果子树没有更新,则缓存相关的widget 代表 了 该子树每次条件允许时复用它。 和创建新的(虽然配置相同的)Widget相比,复用Widget的效率要高得多。 将stateful分解为带有子参数的Widget是执行此操作的常用方法。

  4. Use const widgets where possible. (This is equivalent to caching a widget and re-using it.)
    尽可能使用 const Widget。 (这相当于缓存一个Widget并复用它。)

  5. Avoid changing the depth of any created subtrees or changing the type of any widgets in the subtree. For example, rather than returning either the child or the child wrapped in an IgnorePointer, always wrap the child widget in an IgnorePointer and control the IgnorePointer.ignoring property. This is because changing the depth of the subtree requires rebuilding, laying out, and painting the entire subtree, whereas just changing the property will require the least possible change to the render tree (in the case of IgnorePointer, for example, no layout or repaint is necessary at all).
    避免更改任何已创建出来的子树的深度或避免更改子树中任何Widget的类型。 例如,不要返回包含在 IgnorePointer 中的子Widget或子Widget,而是始终将子Widget包装在 IgnorePointer 中并控制 IgnorePointer.ignoring 属性。 这是因为更改子树的深度需要rebuild、layout和paint整个子树,而仅更改属性将需要对render树进行尽可能少的更改(例如,在 IgnorePointer 的情况下,很必要免去重新layout和 重新paint)。

  6. If the depth must be changed for some reason, consider wrapping the common parts of the subtrees in widgets that have a GlobalKey that remains consistent for the life of the stateful widget. (The KeyedSubtree widget may be useful for this purpose if no other widget can conveniently be assigned the key.)
    如果由于某种原因必须更改深度,请考虑将子树的公共部分包装在具有的 GlobalKey 的Widget中,(该widget 因为GlobalKey)会在StatefulWidget的生命周期内保持一致。 (如果没有其他Widget可以方便地分配密钥,则 KeyedSubtree Widget可能对此有用。)

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值