一起养成写作习惯!这是我参与「编程 · 4 月更文挑战」的第6天,点击查看活动详情。
测试描述
可能很多人会认为,每次的 State#setState
都会触发当前状态类的 build
方法重新构建。但真的是这样吗,你真的了解 Flutter
界面的更新流程吗?
本篇文章将做一个极限测试
,看一下连续触发 1000000
次 setState
会发生什么?是连续触发 1000000
次屏幕更新,导致界面卡死,还是无事发生?用你的眼睛来见证吧!
另外,本文有对应的视频版,可在 哔哩哔哩
进行观看:
【Flutter极限测试 - 连续 setState 1000000 次会怎么样? 】
1、测试代码说明
如下所示,在默认案例基础上添加了两个蓝色文字,点击时分别触发如下的 _increment1
和 _setState1000000
。其中 _setState1000000
是遍历执行 1000000
次 setState
。
void _increment1() {
setState(() {
_counter++;
});
}
void _setState1000000() {
for (int i = 0; i < 1000000; i++) {
setState(() {
_counter++;
});
}
}
2、运行结果
如下是在 profile
模式下,网页调试工具中的测试结果。可以看出即使连续触发了 1000000
次的 steState
,也不会有 1000000
次的帧触发来更新界面。也就是说,并非每次的 steState
方法触发时,都会进行重新构建,所以,你真的懂 State#steState
吗?
3. 源码调试分析
如下,在 State#setState
源码中可以看出,它只做了两件事:
- 触发入参回调 fn 。
- 执行持有元素的
markNeedsBuild
方法。
这里 1121
行的 fn()
做了什么,不用多说了吧。就是 setState
入参的那个自加方法。
此时该 State
中持有的 _element
对象类型是 StatefulEmement
,也就是 MyHomePage
组件创建的元素。
在 Elememt#markNeedsBuild
方法中没有一个非常重要的判断,那就是下面 4440 行
中,如果 dirty
已经是 true
时,则直接返回,不会执行接下来的方法。如果 dirty
是 false
,那接下来会置为 true
。
另外,owner.scheduleBuildFor
用于收集脏元素,以及申请新帧的触发。这就是为什么连续执行 1000000
次 stateState
时,该元素不会加入脏表 1000000
次,不会触发 1000000
帧的原因。
总的来说, State#setState
的核心作用就是把持有的元素标脏
并申请新帧调度
。而只有新帧到来,执行完构建之后,元素的 dirty
才会置为 false
。也就是说,两帧之间,无论调用多少次 setState
,都只会触发一次, 元素标脏
和 申请新帧调度
。这就是为什么连续触发 1000000
次,并无大事发生的原因。
本文就到这里,以后有什么稀奇古怪的测试,还会通过文件 + 视频的方式分享,下次再会 ~
本网站是一个以CSS、JavaScript、Vue、HTML为核心的前端开发技术网站。我们致力于为广大前端开发者提供专业、全面、实用的前端开发知识和技术支持。 在本网站中,您可以学习到最新的前端开发技术,了解前端开发的最新趋势和最佳实践。我们提供丰富的教程和案例,让您可以快速掌握前端开发的核心技术和流程。 本网站还提供一系列实用的工具和插件,帮助您更加高效地进行前端开发工作。我们提供的工具和插件都经过精心设计和优化,可以帮助您节省时间和精力,提升开发效率。 除此之外,本网站还拥有一个活跃的社区,您可以在社区中与其他前端开发者交流技术、分享经验、解决问题。我们相信,社区的力量可以帮助您更好地成长和进步。 在本网站中,您可以找到您需要的一切前端开发资源,让您成为一名更加优秀的前端开发者。欢迎您加入我们的大家庭,一起探索前端开发的无限可能!