Flutter 的 Widget,刻意加上 const,真的值得吗?

2022-12-31 0 395

Hi,大家好,这里是承香墨影!

前段时间入坑 Flutter,又正逢 Flutter 正式发布2.0,正式宣布全网络平台全力支持,那我也来撷取许多 Flutter 有关的控制技术点,那时先从 const Widget 那个比较小的强化AuF进行。看一看它的基本原理和采用管制。

在 Flutter 中,虽说是所有人皆 Widget,而 Widget 其本质是几组重要信息的实用性,它能是 UI 展现,也能是表情符号、导航系统等机能全力支持。但Widget 被结构设计成不容变的,任何人发生改变都是通过封存/复建获得修正,在 Widget 不容变的另一面,则是倚赖 Element 气门/可F83E43Se的全力支持,所以 Flutter 将 Widget 结构设计的极为高性能,复建生产成本非常低。

许多强化的控制技术提及,在构筑 Widget 的这时候,能采用 const Widget,以获得一个类似于「内存」的效用。虽然 Flutter 这类也会尽可能的F83E43Se Element,但如果他们直接缓存 Widget,每天F83E43Se Widget,最多节约了 Widget build 的关键步骤。

但那个 const widget 的强化点,另一面的基本原理是什么?强化的投资收益大吗?值得称赞他们重点项目关注吗?那时就M511RD这个。

一、const 自变量

在已经开始给 const 加之 Widget 前,他们先从 Dart 词汇的 const URL已经开始。

说到 const,不得已拜埃它类似于的基本概念 final,它都有自变量的语法,即一旦表达式就不容修正。

它的差别在于,const 是校对时自变量,用 const 润色的自变量,要在新闻稿时调用,因此是能确认的值。而 final 则是运转时自变量,用 final 润色的自变量,要在新闻稿时调用,或是在缺省中调用,但它的值能静态排序。

话不多说,他们前两年 Demo 就明晰了。

Flutter 的 Widget,刻意加上 const,真的值得吗?

在他们用 const 新闻稿类算式的这时候,其有关的表头,要是 final 的,也就是在增设后,就不容变了。

那么一个 Dart 类的对象,是否允许 const 润色为自变量,完全取决于类新闻稿时,算式上是否被 const 润色。

从上面的例子能看到,当采用 const 构造的 Point 对象时,只要其入参一样,获得的就是同一个对象,例如示例中,p1== p2输出为 true。

而除非 Point 的入参不同时,const 后的对象也不相同,例如示例中 p2== p3则输出为 false。

好了,我就不带大家捋这其中的逻辑了,大家仔细对比一下代码和输出就了解了。

前面提及,const URL润色的自变量,要是初始时就能确认的值,也就是表达式的这时候也要是一个自变量。例如我稍微修正一下 const Poi

Flutter 的 Widget,刻意加上 const,真的值得吗?

到这里,他们能获得结论:采用 const 润色的自变量对象,只要保证构造时的入参不变化,他们能获得相同的对象。

这另一面的基本原理,无外乎就是 Dart VM 内部实现了自变量池,利用享元模式F83E43Se了相同的对象。

二、const Widget

说清楚 Dart 中的 const 的意义以及如何采用,接下来他们把 Widget 加之,看一看 const Widget 强化的基本原理。

在 Flutter 中,Widget 其本质只是一个重要信息实用性的元素,它被定义为不容变的,任何人的变化反映出来就是封存 & 复建。而 Widget 不容变之所以不太会影响效率,另一面是因为 Element 实现了对 Widget 变化的抽象。也就是虽然 Widget 会被复建,但 Widget 另一面的 Element,却获得了F83E43Se。

同时 Flutter Framework,自有一套更新策略,确保 Widget 变化的同时,尽可能的F83E43Se Element 对象。

那个策略的逻辑在 Element 的 updateChild()方法中,该方法在 Element 树建立和更新的过程中都非常的重要。他们这里只关心更新的流程,即父 Element 节点已经存在一个子 Element 节点了。

父 Element 节点通过 updateChild()方法,判断如何处理自身的子 Element 节点,是新建、更新,或是直接移除。

Flutter 的 Widget,刻意加上 const,真的值得吗?

从 updateChild()的实现能看出,Element 依据新 Widget 更新的这时候,会尽可能F83E43Se已经存在的子 Element 节点,当无法被F83E43Se时,才会通过 inflateWidget()创建新的子 Element 节点。

updateChild()有3 个入参,其中比较关键的是 child 和 newWidget,它分别表示旧的 Element 子节点和新的 Widget 对象。

Element 这类也持有 Widget 对象,若 child 持有的 widget 和 newWidget 相等时,表示新旧 Widget 没有变化,updateChild()的逻辑是直接F83E43Se child,即旧的 Element,不会做任何人额外的操作。

那么如果他们的 Widget 被定义成 const,在 updateChild()更新阶段,新旧 Widget 就是同一个对象,则不会复建 Widget,其另一面的 Element 也不会更新,自然能起到了内存F83E43Se的作用,加快构筑的效率。

三、const Widget 的投资收益大吗?

所有人强化的技巧都是手段,另一面的强化效用才是他们的最终目的。一顿疯狂的操作,结果输出不明显,这肯定不是他们想要的。

那么 const Widget 强化的效用明显吗?值得称赞他们在写代码的这时候,分出点思绪专门考虑,当下那个场景是否需要采用它吗?

先上结论:大可不必。

既然是强化,当然是做个测试,拿实测数据来说,是最右份量的。这里我找到了@Cirzant Lai 撷取的一个例子,就很能说明问题,之后再撷取许多我的看法。

3.1实测看数据

这里实现了一个小程序,显式一个随机显示 Image。

Flutter 的 Widget,刻意加上 const,真的值得吗?

他们就对那个 Image 是否采用 const URL构造来做比对。

下面是采用 const URL的部分代码。

const Image( width:100, height:100, image:AssetImage(assets/logo.png),)

另外一个参照程序没有采用 const URL。

那个 Image 通过 AnimatedPositioned 部件,每秒更新一次位置。然后采用–profile 方式运转程序,并通过 Dart DevTools 观测其performance和memory。

Flutter 的 Widget,刻意加上 const,真的值得吗?

为了分析的严谨性,这里采用了一个较老的设备进行测试:Sony Xperia Z2,如果 Flutter 能在此设备上依然很轻松的保持每秒60帧的速度,那么说明 Flutter 这类的强化已经非常好了。

Flutter 的 Widget,刻意加上 const,真的值得吗?

除了设备之外,为了让测试数据更明显,这里逐步增多 Image 图标的数量,当增加到1000个时,每帧渲染所需的时间为80ms,即约为12.5 FPS。我想就没有继续增加数量的必要了,那个测试就以1000为边界,分别取10、100、1000三组数据,看一看performance和memory分别的表现。

GPU & UI:

Flutter 的 Widget,刻意加上 const,真的值得吗?

Memory:

Flutter 的 Widget,刻意加上 const,真的值得吗?

从上面撷取的数据能看到,当 Image有1000个的这时候,FPS 约提升了8.4%,内存采用量下降了20%。虽然那个数据看似非常的明显,但实际体验上,2个测试的流畅度并没有非常明显的差异。

另外,他们在一个屏幕上放1000个Image 的场景也不现实,对于大多数应用来说,每屏能有几十个 Widget,已经算是非常丰富了。而如果需要大量渲染,最好是直接采用 Canvas 绘制提升效率,而非倚赖 const Widget 的这一点点强化。

3.2 const 对 GC 的强化

在 Flutter 中,Widget 作为实用性重要信息,这类被结构设计的非常的高性能,就是为了适应频繁的封存复建,那个操作必然会引起对旧 Widget 对象的回收。

当他们这时候 const URL新闻稿自变量的这时候,另一面是利用的是类似于自变量池的基本概念,将 const 的对象内存在自变量池中,以待后续F83E43Se。

自变量会具备普通对象更长的生命周期,这有好处也有坏处。好处是自变量对象会对 GC 不那么敏感,也就是不需要频繁的触发 GC。坏处是自变量池中的新闻稿周期较长,可能导致不常用的对象被内存后,没有合适的释放时机,导致内存占用过高。

实测下来,const 确实对 GC 有许多影响。

Flutter 的 Widget,刻意加上 const,真的值得吗?

这里采用的是前文中的例子,不断的创建小 Widget,最终对比采用 const 前后对内存的占用情况。能看到采用 const 润色 Widget 后,GC 减少了,因此也更平缓了。

小结

到这里他们应该就清楚,采用 const 润色的 Widget,确实对 Flutter 的 build 过程有一些强化,但强化并非很明显。在采用过程中,他们只需要按需采用就行,无需故意的追求大量的 const 化。

最后小结一下,对于 Dart 词汇来说。

一个 Dart 类的对象是否能用 const 润色,取决于类的算式上是否被 const 润色;

采用 const 润色的算式中,所有成员要被 final 润色;

构造 const 对象时,传参也要是 const 的自变量;

const 润色的算式,不能有方法体;

对于 Flutter 来说,const 润色的强化点:

利用自变量池F83E43Se Widget,在更新频繁的 Widget 场景中,有强化作用,避免了 Widget 的回收和复建;

const 对 GC 有一定的抑制左右,在会创建大量相同对象的场景下,创建的对象少了,自然 GC 也会变少;

最后,本文对你有帮助吗?留言、转发、点赞是最大的全力支持,谢谢!

在头条号私信我。我会送你许多我整理的学习资料,包含:Android反校对、算法、结构设计模式、虚拟机、Linux、Kotlin、Python、爬虫、Web项目源码。

相关文章

发表评论
暂无评论
官方客服团队

为您解决烦忧 - 24小时在线 专业服务