
最近在着手开发我的 《匠心星问》 ,它定位是一款 题库 应用,将集题目浏览、发布、解答、做题为一体。打算第一步先以 Flutter 为核心,准备题库资源。于是诞生《每日一题》 系列,准备精心设计一些 Flutter 的问题与解答,作为题库的养料。本文的焦点是探讨:
如何理解 Widget 的不可变性
Widget 的不可变性是 Flutter 实现热重载、高性能渲染以及组件复用的基础,是理解 Flutter 架构和开发思维的重要一环。理解 Widget 的不可变性,是打开 Flutter 编程之门的钥匙。
- | - |
---|---|
![]() |
![]() |
1. 什么是 Widget 的不可变性
在 Flutter 中,Widget 是构建 UI 的基本单元, 在 Flutter 源码 中对 Widget 类注释中,有着这样一句表述 :
一个 Widget 是对 UI 界面某部分
不可变的描述
。

许多初学者常常对 Widget「不可变」的特性感到困惑。简单来说,不可变性指的是:
一旦 Widget 对象被创建,其属性就不能更改。
比如下面的 Text
组件创建之后,其中的 张风捷特烈
内容以及样式等配置数据,都不能变动:

dart
Text text = Text('张风捷特烈');
如果你想让字号变大呈红色 , 此时你 不能修改
上面 text 对象的任何属性,而是要 创建一个新的Text对象 来替代原来的。

dart
❌ 为样式赋值修改
text.style = TextStyle(fontSize: 20, color: Colors.red)
✅ 创建新的 Text 对象
Text newText = Text(
'张风捷特烈',
style: TextStyle(fontSize: 20, color: Colors.red),
)
2. Widget 不可变性的保证
如何在代码层面保证使用者不会修改 Widget 的成员呢? 答案很简单: 使用 final 修饰 。
熟悉 Flutter 的朋友可能都知道,官方所有组件的所有普通成员,都会通过 final 关键字修饰(如下 Text 组件)。着就从根本上扼杀了开发者修改属性的可能:

而如果你尝试在自定义的 Widget 中定义一个非 final 修饰的普通成员时,就会收到一个警告,提醒你 Widget 的所有属性都需要是不可变的。

这两者就可以保证在开发过程中,开发者 不会
也 不能
修改已存在的 Widget 对象。
3. 不可变性的意义是什么
在 Flutter 中,Widget 并不是动态变化的 UI 元素 ,它更像是一张 描述当前 UI 的结构图
------就像你在某一时刻截下的一张静态 UI 照片。这张图不会变,它只是告诉框架"这一帧 UI 应该长什么样"。
当状态发生变化时,Flutter 不会去修改已有的 Widget,通过重建Widget树生成新的配置描述,形成下一帧的新"快照"。 这样通过 状态数据
和 布局结构
就能重现当时的界面,也就是可预测 UI 状态。
- 符合声明式编程范式 :不可变性是声明式 UI 的核心,能根据状态构建出完整的界面,而无需手动操作更新流程。
- 简化 UI 构建逻辑 : 不可变性让 Widget 成为一种 纯 UI 描述,代码更易于理解和维护。
- 状态分离更清晰 :所有变化都交由状态数据管理处理,Widget 本身保持纯净,有助于模块化和复用。
- 提升性能 : 空间可以通过比较新旧 Widget 来判断是否复用底层的渲染对象,避免不必要的重建和开销。
- 热重载的基础 : 不可变的 Widget 架构,让 Flutter 能够快速替换 UI 树中的节点,从而实现毫秒级的热重载体验。

4. Widget 不可变,界面如何变化呢?
我们都知道,在 Flutter 中 Widget 是界面表现的决定因素,那么 Widget 不可变,是否意味着 界面不可变 呢? 答案显然是否定的。
Widget 是某一帧界面的配置数据,Flutter 的渲染机制是基于 重建(build)
思想运作的:每当状态数据发生变化,Flutter 并不会去修改已有的 Widget,而是重新构建新的 Widget 。来描述在当前状态下,界面应有的样子。Flutter 会将其与上一帧的 Widget 树进行对比,找出差异,并仅更新需要变化的部分。这种 状态驱动 + Widget 重建 的方式,使得 UI 变化既高效又可控,同时充分发挥了声明式编程的优势。
打个比方,在餐厅点餐,菜单(Widget)是不会变的 ,它只是描述了每道菜长什么样、有哪些配料。你点了一道超辣牛肉热拌面,订单提交后。但过一会你改变口味(状态变化),想起来今天不能吃辣。服务员不会去 修改
你原来的订单,而是重新生成一份新的 不辣牛肉热拌面
订单。
同样地,Flutter 并不会修改原来的 Widget,而是根据当前状态重新 "上菜" ------ 构建一个新的 Widget。这种做法避免了直接修改原有内容带来的混乱,也让整个界面的更新过程更加清晰、有序、高效。你看到的"界面变化",其实是状态变化后,框架重新声明了一道 "新菜"。
5. 小结
我在这里给出这道题的简要回答:
Q:如何理解 Widget 的不可变性
A: 在 Flutter 中,Widget 是构建 UI 界面的基本单位,它本质上是不可变(immutable) 的。所谓不可变,指的是一旦 Widget 被创建,其属性就不能再被修改。每一个 Widget 实例只是用来描述某一帧 UI 的外观,它本身不持有
布局、渲染或状态等信息数据。理解这一特性对于掌握 Flutter 的声明式 UI 编程至关重要。因为 Widget 不可变,界面的变化并不是修改旧的 Widget,而是根据新的状态,重新构建新的 Widget 。Flutter 会将新旧 Widget 树进行对比(diff),并智能地更新 Element 树和底层渲染结构,只改变必要的部分,从而实现高效渲染。
如果你有其他的看法,或者有什么想要的题目、或者想提供题目和答案,都欢迎在评论区留言。更多文章和视频知识资讯,大家可以关注我的公众号、掘金和 B 站 。