Flutter 的“状态管理”一开始看起来玄乎,学着学着又发现:其实就是一句话——数据变了,界面要跟着变。
我刚入门的时候最容易卡住的点,不是写不出代码,而是不知道“这一行状态应该放哪、该用什么方式更新”。这篇我就按自己的使用习惯,把入门阶段最常见的几条路捋一遍:从 setState 开始,过渡到 ValueNotifier,最后到 ChangeNotifier + Provider 这种更适合项目组织的写法。
1)先把“状态”讲人话
在我理解里,Flutter 的 state 就两类:
- 短命状态:只在某个页面/组件里用(输入框内容、选中项、展开/收起)
- 长命状态:跨页面、跨模块共享(登录信息、购物车、主题/语言、全局配置)
短命状态很多时候 setState 就够了;长命状态一多,才需要更系统的管理方式。
2)第一站:setState(别嫌它土,真香)
如果你只是做一个页面的小交互,setState 是最省心的。
1 | class CounterPage extends StatefulWidget { |
我对 setState 的使用边界也很明确:
- 页面内部状态 → 用它
- 一旦要跨组件共享、或者逻辑开始变复杂 → 立刻换工具
3)第二站:ValueNotifier(轻量、好用、我用得很多)
ValueNotifier 适合那种“一个值驱动一块 UI”的场景,比 setState 更干净一些,尤其适合把状态从 widget 里挪出来一点点,但又不想引入整套状态管理框架。
1 | class LikeButton extends StatefulWidget { |
它的好处是:你不会把整个页面都 setState 一遍,而是把重建范围锁在 ValueListenableBuilder 里。
4)第三站:ChangeNotifier(当你开始“管理一坨状态”)
当状态不再是一个值,而是一组数据 + 一些业务操作(比如登录、购物车、个人资料),我会直接用 ChangeNotifier 把这些东西“收进一个类里”。
1 | class CartModel extends ChangeNotifier { |
到这一步,你已经在做两件很重要的事:
- 把 UI 和业务逻辑分开
- 让状态可以被多个地方复用
5)把 ChangeNotifier 用起来:Provider(入门阶段很稳)
光有 ChangeNotifier 不够,你还需要一个“把它挂到 widget tree 上”的方式。入门阶段我最常用的是 provider(生态成熟、资料多、上手快)。
① 顶层注入
1 | MultiProvider( |
② 在页面里读取/监听
1 | // 只读一次(不监听刷新) |
如果你不想让整个页面跟着刷新,可以用 Consumer 或 Selector 把刷新范围缩小:
1 | Consumer<CartModel>( |
6)我怎么选:别一上来就“宇宙级方案”
我自己的选择顺序大概是:
- 只是一个页面的小状态 →
setState - 一个值驱动局部 UI →
ValueNotifier - 一组状态 + 一堆操作要复用 →
ChangeNotifier - 需要跨页面共享、组织项目 →
ChangeNotifier + Provider
你会发现:这条路线其实就是“从简单到可维护”。
别急着追最炫的框架,先把项目写顺,后面再换也不迟。
结尾
状态管理说到底不是背 API,而是做取舍:把状态放在离它“最近、最合理”的地方。
你现在如果正在写一个具体页面(比如登录页、购物车、个人中心),把结构发我,我可以按你的业务给一个更贴近实际的拆分建议:哪些用 setState,哪些上 ChangeNotifier,哪些该做成全局。