17.Flutter 零基础入门(十七):StatelessWidget 与 State 的第一次分离

Flutter 零基础入门(十七):StatelessWidget 与 State 的第一次分离

在上一篇中,我们已经正式进入 Flutter,并完成了:

  • 第一个 Flutter 页面
  • Widget 树的理解
  • StatelessWidget 与 build 方法

但你一定会产生一个疑问:

👉 如果页面内容要变化怎么办?

👉 按钮点击后,文字如何改变?

这一篇,我们来解决 Flutter 中最核心的问题

👉 状态(State)从哪里来?


一、StatelessWidget 的边界

先回顾 StatelessWidget:

dart 复制代码
class MyWidget extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return Text('Hello');
  }
}

特点非常明确:

  • 没有状态
  • 内容固定
  • 一旦创建,不会变化

📌 所以:

StatelessWidget 天生不适合"会变的 UI"


二、什么是 State(状态)?

在 Flutter 中,状态指的是:

影响 UI 显示的数据

例如:

  • 计数器的数字
  • 是否登录
  • 是否加载中
  • 当前选中项

📌 一句话理解:

状态变了,UI 就该变


三、一个"错误但常见"的新手尝试

复制代码
class Counter extends StatelessWidget {
  int count = 0;

  @override
  Widget build(BuildContext context) {
    return Text('$count');
  }
}

你可能会想:

count 不就行了吗?

❌ 这是行不通的。

原因是:

  • StatelessWidget 不会监听变量变化
  • Flutter 不会重新 build

四、StatefulWidget 的出现

为了解决"UI 需要变化"的问题,Flutter 引入了:

👉 StatefulWidget

它的核心思想是:

Widget 负责描述 UI
State 负责保存和管理状态


五、StatefulWidget 的基本结构

复制代码
class Counter extends StatefulWidget {
  @override
  State<Counter> createState() {
    return _CounterState();
  }
}

对应的 State:

复制代码
class _CounterState extends State<Counter> {
  int count = 0;

  @override
  Widget build(BuildContext context) {
    return Text('$count');
  }
}

📌 注意:

  • Widget 和 State 是两个类
  • State 才是真正"活着的部分"

六、为什么要拆成两个类?

这是 Flutter 的设计核心

  • Widget:不可变(immutable)
  • State:可变(mutable)

好处:

  • UI 描述稳定
  • 状态变化可控
  • Flutter 可以高效更新界面

七、setState:状态变化的"开关"

仅仅修改变量是不够的

复制代码
count++;

你必须告诉 Flutter:

状态变了,需要重新 build

这就是 setState 的作用。


八、setState 的正确用法

复制代码
setState(() {
  count++;
});

含义是:

  • 在回调中修改状态
  • Flutter 重新调用 build

📌 本质:

setState = 通知 Flutter 刷新 UI


九、一个完整的计数器示例

复制代码
class Counter extends StatefulWidget {
  @override
  State<Counter> createState() => _CounterState();
}

class _CounterState extends State<Counter> {
  int count = 0;

  @override
  Widget build(BuildContext context) {
    return Column(
      mainAxisAlignment: MainAxisAlignment.center,
      children: [
        Text('当前计数:$count'),
        ElevatedButton(
          onPressed: () {
            setState(() {
              count++;
            });
          },
          child: Text('加 1'),
        ),
      ],
    );
  }
}

十、State 是如何驱动 UI 的?

流程非常重要:

1️⃣ 用户点击按钮

2️⃣ 调用 setState

3️⃣ Flutter 标记当前 State 为"脏"

4️⃣ build 重新执行

5️⃣ UI 更新

📌 你不需要手动操作 UI。


十一、Widget、State、build 的关系图

复制代码
StatefulWidget(不可变)
        ↓
     State(可变)
        ↓
     build()
        ↓
       UI

这张图,你以后会反复用到。


十二、新手最容易犯的错误

❌ 在 build 中写逻辑

❌ 忘记使用 setState

❌ 把状态写在 StatelessWidget 中

记住一句话:

状态只存在于 State 中


十三、这一篇你真正理解了什么?

你已经理解了 Flutter 的核心哲学:

UI 是状态的映射结果

这也是 Flutter、React、Vue 的共同思想。


十四、总结

本篇你学会了:

  • StatelessWidget 的边界
  • 什么是 State
  • StatefulWidget 的结构
  • setState 的作用

你已经正式跨入:

Flutter 状态驱动 UI 的世界


🔜 下一篇预告

《Flutter 零基础入门(十八):StatefulWidget 生命周期初识》

下一篇我们将学习:

  • initState 是什么时候执行的?
  • dispose 是干什么的?
  • State 的生命周期顺序
  • 为什么要释放资源?

从下一篇开始:

你将真正理解 Flutter 页面"从出生到销毁"的全过程

相关推荐
一起养小猫9 分钟前
Flutter for OpenHarmony 实战:2048游戏完整开发指南
flutter·游戏·harmonyos
念越10 分钟前
数据结构:栈堆
java·开发语言·数据结构
a11177617 分钟前
图书借阅管理系统(FastAPI + Vue)
前端·vue.js·fastapi
淮北49432 分钟前
pip虚拟环境包的问题
开发语言·python·pip
dear_bi_MyOnly34 分钟前
【多线程——线程状态与安全】
java·开发语言·数据结构·后端·中间件·java-ee·intellij-idea
常年游走在bug的边缘35 分钟前
掌握JavaScript作用域:从函数作用域到块级作用域的演进与实践
开发语言·前端·javascript
jiaguangqingpanda40 分钟前
Day36-20260204
java·开发语言
极致♀雨1 小时前
vue2+elementUI table表格勾选行冻结/置顶
前端·javascript·vue.js·elementui
ctyshr1 小时前
C++编译期数学计算
开发语言·c++·算法
打码的猿1 小时前
Qt对话框不锁死主程序的方法
开发语言·qt