
最近在着手开发我的 《匠心星问》 ,它定位是一款 题库 应用,将集题目浏览、发布、解答、做题为一体。打算第一步先以 Flutter 为核心,准备题库资源。于是诞生《每日一题》 系列,准备精心设计一些 Flutter 的问题与解答,作为题库的养料。本文的焦点是探讨:
说说 StatelessWidget 从诞生到 build 的流程
在 Flutter 中,build
函数是自定义组件最核心的部分,负责构建和组合 UI 界面。但它的触发是 Flutter 框架内部的行为,理解 build
函数的触发时机,不仅有助于我们更清晰地把握界面构建流程,也能够加深对 Flutter 框架运行逻辑的理解。
1.调试案例
这里以最简单的颜色展示位案例来介绍,如下所示: 自定义一个 ColorView
组件展示颜色,在 MyApp 中构建。我们将专注于 ColorView 从诞生到 build
的流程:
dart
void main() {
runApp(MyApp());
}
class MyApp extends StatelessWidget {
const MyApp({super.key});
@override
Widget build(BuildContext context) {
return ColorView(color: Colors.blue);
}
}
class ColorView extends StatelessWidget {
final Color color;
const ColorView({super.key, required this.color});
@override
Widget build(BuildContext context) {
return ColoredBox(color: color);
}
}
想要知道 ColorView#build
的触发时机,只要在断点调试一下就行了。如下,可以看到 build 函数触发时的方法栈调用信息。从这里就可以分析出该方法是如何被 Flutter 框架触发的。

2. StatelessElement 与 build 的渊源
从方法栈中可以看出,ColorView#build
是被 StatelessElement#build
调用的。点击进入可以看到:
- 这里可以通过 widget 成员拿到 ColorView 对象;
Widget#build
中回调的 BuildContext 参数,就是这里的StatelessElement
对象。

3. 从 mount 开始的新生命
当继续检阅下方的方法栈,同时观察 this 对象。其中 build
、performRebuild
、rebuild
、_firstBuild
、mount
四个函数的 this 指向的都是 持有 ColorView 的 StatelessElement 对象。
直到 Element.inflateWidget
时 this 变成了 MyApp 对应的元素,这块代码中有着丰富的信息:
- 在这里
newWidget
是 ColorView 组件,通过函数参数传入: - 在这里 newWidget 触发了
createElement
方法,创建了newChild
元素对象。 - newChild 元素创建完成后,执行 mount ,从而触发 build 工作流。

从这里不难看出 Element.inflateWidget
对应的对象,是父级元素节点。通过该方法得到子级元素节点进行更新。
4. 父节点更新子节点
再往下看一帧,inflateWidget
是由 updateChild
触发的,该方法返回 Element 对象。并且 newWidget 也是入参传递过来的:

再往下,来到了 Element
的 performRebuild
方法:
- 从 5715 行可以看到,上面
newWidget
的来源于build()
函数。 - 从 5738 行可以看到,上面
inflateWidget
返回的子元素,将作为当前元素的子节点:

当前的 Element 对象是 MyApp 组件对应的 StatelessElement
, 它的 build 方法使用的是对应 Widget的 build:

也就是说,会触发 MyApp#build
返回 ColorView 对象。这就是 ColorView 组件诞生的时机:

5. 总结
到这里,从头到尾梳理一下,StatelessWidget 从诞生到 build 的完整流程。初次的构建流程发生在,父元素节点更新子节点时,会触发 build
方法得到组件,然后通过 inflateWidget
创建子元素节点,并触发子元素 mount 方法。在挂载期间触发首次的构建流程,最终触发对应组件的 build 回调。
sh
Element.performRebuild # 父元素节点更新子节点
Element.build # 组件对象诞生
Element.inflateWidget # 生成子元素节点
Widget.createElement() # 创建子元素节点
Element.mount() # 创建子元素节点开始装在
[Stateless]Element._firstBuild -> rebuild -> performRebuild -> build # 触发元素构建流
[Stateless]Element.build # 触发组件构建
如果你有其他的看法,或者有什么想要的题目、或者想提供题目和答案,都欢迎在评论区留言。更多文章和视频知识资讯,大家可以关注我的公众号、掘金和 B 站 。