大家好,我是展菲,目前在上市企业从事人工智能项目研发管理工作,平时热衷于分享各种编程领域的软硬技能知识以及前沿技术,包括iOS、前端、Harmony OS、Java、Python等方向。在移动端开发、鸿蒙开发、物联网、嵌入式、云原生、开源等领域有深厚造诣。
图书作者:《ESP32-C3 物联网工程开发实战》
图书作者:《SwiftUI 入门,进阶与实战》
超级个体:COC上海社区主理人
特约讲师:大学讲师,谷歌亚马逊分享嘉宾
科技博主:华为HDE/HDG
我的博客内容涵盖广泛,主要分享技术教程、Bug解决方案、开发工具使用、前沿科技资讯、产品评测与使用体验。我特别关注云服务产品评测、AI 产品对比、开发板性能测试以及技术报告,同时也会提供产品优缺点分析、横向对比,并分享技术沙龙与行业大会的参会体验。我的目标是为读者提供有深度、有实用价值的技术洞察与分析。
展菲:您的前沿技术领航员
👋 大家好,我是展菲!
📱 全网搜索“展菲”,即可纵览我在各大平台的知识足迹。
📣 公众号“Swift社区”,每周定时推送干货满满的技术长文,从新兴框架的剖析到运维实战的复盘,助您技术进阶之路畅通无阻。
💬 微信端添加好友“fzhanfei”,与我直接交流,不管是项目瓶颈的求助,还是行业趋势的探讨,随时畅所欲言。
📅 最新动态:2025 年 3 月 17 日
快来加入技术社区,一起挖掘技术的无限潜能,携手迈向数字化新征程!
文章目录
- 前言
- 状态为什么会“爆炸”?不是 Flutter 的锅
- 状态从什么时候开始失控?
- Flutter 和前端,状态模型几乎是同构的
- 对比一下两边的状态形态
- 前端 / RN
- Flutter
- 一个 Flutter 中最典型的“状态开始失控”的例子
- 初期写法:状态直接写在页面里
- Provider / Riverpod / Bloc,其实是在解决同一件事
- 一个最基础的 Provider Demo
- 这和 Redux / Zustand 有什么区别?
- RN 项目为什么会掉进 Redux 地狱?
- iOS 状态为什么看起来更“稳定”?
- iOS 的“稳定”,来自强约束
- 但代价是什么?
- 真正通用的,是“状态分层”,而不是具体框架
- 一个跨技术栈通用的状态分层模型
- 本地 UI 状态
- 页面业务状态
- 全局状态
- 用 Flutter 再写一版“分层正确”的 Demo
- 总结
前言
如果你写 Flutter 写到一定阶段,迟早会遇到一个问题:
项目一开始很简单,用
setState就够了
过一阵子开始加 Provider
再后来又有人提 Riverpod / Bloc
最后大家都在问:我们到底该用哪个?
如果你有前端或者 RN 经验,这一幕其实一点都不陌生。
Redux、MobX、Zustand、Recoil……
前端早就经历过一次完整的“状态管理百家争鸣”。
那问题来了:
为什么 Flutter 这么快就走上了和前端一模一样的路?
状态为什么会“爆炸”?不是 Flutter 的锅
先说一个很多人不太愿意承认的事实:
状态复杂化,几乎是所有中大型应用的必经之路。
状态从什么时候开始失控?
你回忆一下项目的演进路径,通常是这样的:
- 一开始:
页面里几个变量,setState很香 - 业务变复杂:
表单、列表、筛选条件、分页状态开始增多 - 再后来:
登录态、用户信息、权限、配置、缓存 - 最后:
多页面共享状态 + 异步 + 回退恢复
这时候你会发现一个很现实的问题:
状态已经不再属于“某一个 Widget / 页面”了。
而一旦状态开始跨页面、跨模块存在,单纯的 setState 就一定会崩。
Flutter 和前端,状态模型几乎是同构的
这也是为什么 Flutter 会自然长出一堆状态管理方案。
因为Flutter 和 React 本质上解决的是同一个问题:
UI = f(State)
状态一变,就要重新描述 UI。
对比一下两边的状态形态
前端 / RN
- 组件本地状态
- 页面级状态
- 全局状态(用户、配置、权限)
Flutter
- Widget 内部 State
- 页面级 State(ViewModel / Controller)
- 全局 State(Provider / Riverpod)
你会发现,层级是一模一样的,只是名字不同。
一个 Flutter 中最典型的“状态开始失控”的例子
先看一个非常常见的写法。
初期写法:状态直接写在页面里
classUserPageextendsStatefulWidget{@overrideState<UserPage>createState()=>_UserPageState();}class_UserPageStateextendsState<UserPage>{bool loading=false;StringuserName='';Future<void>loadUser()async{setState((){loading=true;});awaitFuture.delayed(Duration(seconds:1));setState((){userName='Tom';loading=false;});}@overridevoidinitState(){super.initState();loadUser();}@overrideWidgetbuild(BuildContextcontext){returnloading?CircularProgressIndicator():Text('Hello$userName');}}一开始看起来没毛病。
但问题很快就会出现:
- 用户信息被多个页面用
- 页面返回时状态要保留
- 刷新、错误、空态开始增多
你会发现:
页面既负责 UI,又负责业务状态,又负责异步流程。
这一步,就是 Flutter 和前端一起迈进“状态复杂区”的开始。
Provider / Riverpod / Bloc,其实是在解决同一件事
很多 Flutter 新手会纠结:
Provider 和 Riverpod 到底差在哪?
Bloc 是不是太重了?
但从设计目标来看,它们高度一致:
把状态从 Widget 中“拎出来”
一个最基础的 Provider Demo
classCounterModelextendsChangeNotifier{int count=0;voidincrement(){count++;notifyListeners();}}voidmain(){runApp(ChangeNotifierProvider(create:(_)=>CounterModel(),child:MyApp(),),);}classCounterViewextendsStatelessWidget{@overrideWidgetbuild(BuildContextcontext){finalcounter=context.watch<CounterModel>();returnColumn(children:[Text('Count:${counter.count}'),ElevatedButton(onPressed:counter.increment,child:Text('Add'),),],);}}这和 Redux / Zustand 有什么区别?
如果你把语言换一下:
- ChangeNotifier ≈ Store
- notifyListeners ≈ dispatch
- watch ≈ subscribe
逻辑结构几乎完全一致。
Flutter 并不是“模仿前端”,
而是在声明式 UI 体系下,状态管理只有这一条路能走。
RN 项目为什么会掉进 Redux 地狱?
这件事对 Flutter 其实是一个非常重要的警示。
Redux 出问题,从来不是因为它“设计不好”,而是因为:
- 所有状态都被塞进全局 Store
- 页面级、组件级状态没有边界
- 一点小交互也要走 action → reducer
结果就是:
状态集中化过度,反而失去可维护性。
Flutter 如果无脑全局 Provider / Riverpod,结局是一模一样的。
iOS 状态为什么看起来更“稳定”?
很多 iOS 开发者会说:
我写 UIKit / MVVM,很少纠结状态管理。
这是因为 iOS 用的是另一套代价体系。
iOS 的“稳定”,来自强约束
- 页面生命周期固定
- Controller 持有 View
- 数据流向非常明确
你要更新什么,就直接调方法。
viewModel.userName="Tom"view.update()不会有“自动重建整棵 UI 树”这件事。
但代价是什么?
- 状态复用成本高
- 跨页面共享复杂
- 多端复用几乎不可能
iOS 的稳定,是用灵活性和扩展性换来的。
真正通用的,是“状态分层”,而不是具体框架
如果你横向看 Flutter / 前端 / iOS,会发现一个共识:
状态不是越集中越好,而是各归其位。
一个跨技术栈通用的状态分层模型
本地 UI 状态
- loading
- checkbox 勾选
- 动画开关
放在 Widget / Component 内部
页面业务状态
- 列表数据
- 表单内容
- 页面筛选条件
放在 ViewModel / Controller / Notifier
全局状态
- 登录态
- 用户信息
- 配置、权限
少而精,慎重放全局
用 Flutter 再写一版“分层正确”的 Demo
classUserStateextendsChangeNotifier{StringuserName='';bool loading=false;Future<void>loadUser()async{loading=true;notifyListeners();awaitFuture.delayed(Duration(seconds:1));userName='Tom';loading=false;notifyListeners();}}classUserPageextendsStatelessWidget{@overrideWidgetbuild(BuildContextcontext){finalstate=context.watch<UserState>();if(state.loading){returnCircularProgressIndicator();}returnText('Hello${state.userName}');}}- UI 只关心展示
- 状态逻辑集中
- 页面结构清晰
这套结构,在 React、Flutter、甚至 SwiftUI 中都成立。
总结
Flutter 走向“状态管理百家争鸣”,不是偶然,而是必然:
- 声明式 UI → 状态成为核心资产
- 项目变大 → 状态必然外提
- 外提之后 → 就一定会有流派之争