🎬 HoRain云小助手:个人主页
🔥 个人专栏: 《Linux 系列教程》《c语言教程》
⛺️生活的理想,就是为了理想的生活!
⛳️ 推荐
前些天发现了一个超棒的服务器购买网站,性价比超高,大内存超划算!忍不住分享一下给大家。点击跳转到网站。
专栏介绍
专栏名称 | 专栏介绍 |
《C语言》 | 本专栏主要撰写C干货内容和编程技巧,让大家从底层了解C,把更多的知识由抽象到简单通俗易懂。 |
《网络协议》 | 本专栏主要是注重从底层来给大家一步步剖析网络协议的奥秘,一起解密网络协议在运行中协议的基本运行机制! |
《docker容器精解篇》 | 全面深入解析 docker 容器,从基础到进阶,涵盖原理、操作、实践案例,助您精通 docker。 |
《linux系列》 | 本专栏主要撰写Linux干货内容,从基础到进阶,知识由抽象到简单通俗易懂,帮你从新手小白到扫地僧。 |
《python 系列》 | 本专栏着重撰写Python相关的干货内容与编程技巧,助力大家从底层去认识Python,将更多复杂的知识由抽象转化为简单易懂的内容。 |
《试题库》 | 本专栏主要是发布一些考试和练习题库(涵盖软考、HCIE、HRCE、CCNA等) |
目录
⛳️ 推荐
专栏介绍
Flutter 状态管理——全景指南(2026 实战视角)
一、先想清楚一个问题:你管的是什么"状态"?
二、方案全景图——从简单到企业级
1️⃣ setState——被低估的原生之力
2️⃣ ValueNotifier/ ValueListenableBuilder——轻量共享的甜点区
3️⃣ Provider ——官方亲儿子,但今天更像是"历史桥梁"
4️⃣ Riverpod ★★★ ——2025–2026 新项目最推荐的选择
最小上手(现代写法 · Riverpod 3.x)
异步状态——Riverpod 的杀手级体验
为什么 Riverpod 赢得今天?
5️⃣ Bloc / Cubit ——企业级"重型武器"
6️⃣ GetX ——快,但要清醒对待
7️⃣ Signals ——冉冉升起的轻量派
三、横向速查表
四、选型决策树(照着套就行)
五、最常见的坑(省你两小时调试)
六、给你的下一步建议
Flutter 状态管理——全景指南(2026 实战视角)
一、先想清楚一个问题:你管的是什么"状态"?
Flutter 把状态分为两层,这个区分决定你用什么方案:
类型 | 含义 | 典型例子 | 该用啥 |
|---|---|---|---|
Ephemeral(局部状态) | 只属于某一个 Widget 自己用的临时状态 | 页码计数器、BottomSheet 打开/关闭、TextField 的 obscureText、动画控制器 |
|
App State(应用状态) | 多个地方需要共享/持久化的业务状态 | 登录用户信息、购物车、主题/语言设置、认证 token | Riverpod / Bloc 这类真正的状态管理器 |
🔑 经验法则:能
setState解决的就别升级架构。状态管理最大的坑不是选错库,是过度工程化——把一个开关变量的 toggle 写成三层 Provider + 两个 Model 类。
二、方案全景图——从简单到企业级
复杂度 ───────────────────────────────────────────→ [setState] → [ValueNotifier] → [Provider] → [Riverpod] → [Bloc/Cubit] ↑ ↑ ↑ ↑ ↑ 局部状态 轻量共享 入门/遗留 新项目首选 大型/强规范1️⃣setState——被低估的原生之力
class _ToggleDemo extends State<StatefulWidget> { bool _on = false; @override Widget build(BuildContext context) { return Switch( value: _on, onChanged: (v) => setState(() => _on = v), // 局部,完全合理 ); } }什么时候该从 setState 毕业?
同一个状态需要在不同 Widget / 不同路由中读取或修改
业务逻辑越来越厚,需要单独测试
你开始在父 Widget 层层传 callback,"prop drilling" 痛了
2️⃣ValueNotifier/ValueListenableBuilder——轻量共享的甜点区
当你只有一两个值需要跨组件共享,又觉得 Provider 重:
// 定义在某个模块/全局 final counterNotifier = ValueNotifier<int>(0); // UI ValueListenableBuilder<int>( valueListenable: counterNotifier, builder: (_, value, __) => Text('$value'), ); // 修改 counterNotifier.value++;优点:零依赖、精准重建;缺点:多个状态就散架了,缺依赖注入和组合能力。
3️⃣ Provider ——官方亲儿子,但今天更像是"历史桥梁"
Provider 本质是InheritedWidget + ChangeNotifier 的薄封装,由 Flutter 团队成员 Remi 开发,曾是官方文档教学首选。
// 定义 class Counter extends ChangeNotifier { int value = 0; void inc() { value++; notifyListeners(); } } // 注入 ChangeNotifierProvider( create: (_) => Counter(), child: MyApp(), ) // 消费 Consumer<Counter>( builder: (_, c, __) => Text('${c.value}'), ) // 或 context.watch<Counter>() / context.read<Counter>().inc()为什么新项目现在不首推它了:
痛点 | 说明 |
|---|---|
依赖 | 不能在纯 Dart 层/工具类中读状态 |
运行时查找 | 拼错类型 → |
重建粒度过粗 |
|
无内置异步抽象 | loading / error / data 三态要手写 |
📌今天对 Provider 的定位:已有老项目继续维护 ✅;教新手理解 InheritedWidget ✅;新项目一般直接上 Riverpod。
4️⃣ Riverpod ★★★ ——2025–2026 新项目最推荐的选择
Riverpod 是 Provider同作者做的下一代方案,专门解决上述痛点:状态活在Widget 树之外、编译时安全、不依赖
BuildContext。
最小上手(现代写法 · Riverpod 3.x)
dependencies: flutter_riverpod: ^3.3.1 riverpod_annotation: ^2.6 dev_dependencies: build_runner: ^2.4 riverpod_generator: ^2.6// main.dart void main() => runApp(ProviderScope(child: MyApp())); // ---- 状态定义 ---- // counter_provider.dart import 'package:riverpod_annotation/riverpod_annotation.dart'; part 'counter_provider.g.dart'; @riverpod class Counter extends _$Counter { @override int build() => 0; void increment() => state++; } // ---- UI消费 ---- // 用 Consumer 拿到 ref Consumer( builder: (context, ref, _) { final count = ref.watch(counterProvider); return Column( children: [ Text('$count', style: TextStyle(fontSize: 32)), FilledButton( onPressed: () => ref.read(counterProvider.notifier).increment(), child: Text('+1'), ), ], ); }, ) // 或直接:继承 HookConsumerWidget / ConsumerWidget class HomePage extends ConsumerWidget { @override Widget build(BuildContext context, WidgetRef ref) { final count = ref.watch(counterProvider); return Scaffold( body: Center(child: Text('$count')), floatingActionButton: FloatingActionButton( onPressed: () => ref.read(counterProvider.notifier).increment(), ), ); } }异步状态——Riverpod 的杀手级体验
@riverpod Future<User> userProfile(UserProfileRef ref) async { final repo = ref.watch(authRepositoryProvider); return repo.fetchProfile(); } // UI ref.watch(userProfileProvider).when( loading: () => CircularProgressIndicator(), error: (e, _) => Text('出错: $e'), data: (user) => Text('你好, ${user.name}'), );AsyncValue把loading / error / data 三态变成了类型安全的模式匹配,不用再满屏写bool _isLoading。
为什么 Riverpod 赢得今天?
能力 | 效果 |
|---|---|
编译时安全 | provider 拼写错 → 编译期报错,不是运行时崩溃 |
无 Context 依赖 | 在 Repository / utils 里也能 |
自动 dispose | 页面关掉 → 状态自动清理,无内存泄漏 |
Family / autoDispose | 参数化状态( |
可测试 |
|
组合性强 |
|
📌结论:如果你现在开新项目且没特殊约束 → 选 Riverpod。
5️⃣ Bloc / Cubit ——企业级"重型武器"
Bloc 强制走Event → Bloc → State 管道,所有状态变化可追踪、可审计。多人团队 + 复杂业务流(支付、表单向导、审批链)时,这种"仪式感"就是价值。
// event sealed class CounterEvent {} class Increment extends CounterEvent {} // bloc class CounterBloc extends Bloc<CounterEvent, int> { CounterBloc() : super(0) { on<Increment>((_, emit) => emit(state + 1)); } } // UI FloatingActionButton( onPressed: () => context.read<CounterBloc>().add(Increment()), ) BlocBuilder<CounterBloc, int>( builder: (_, count) => Text('$count'), )Cubit 是 Bloc 的简化版(直接调方法,不用定义 Event),日常 70% 场景够用。
什么时候 Bloc 值得:
金融 / 医疗 / 政务等需要状态变更可审计
10+ 人团队,你需要一个强约定让所有人写同一种结构
流程复杂到"谁改了状态、从哪来的"成了日常 debug 问题
代价:样板代码多、学习曲线陡。
6️⃣ GetX ——快,但要清醒对待
GetX 把状态+路由+DI 捆在一起,写起来极爽,但全局单例默认不释放、魔法太多导致大型项目难追踪难维护,社区对其长期治理风险已有大量讨论。
务实建议:个人项目/黑客松能用;商业产品新项目不建议押注;已有 GetX 老项目别冲动全量重构,但要规划迁移预算。
7️⃣ Signals ——冉冉升起的轻量派
受 SolidJS/Preact 启发,走fine-grained reactivity(精确到某个值变化只刷那一行 UI)。flutter_hooks+ signals 实验性质活跃,在性能敏感场景(实时行情、游戏、低端机)很有想象空间,但尚未取代 Riverpod/Bloc 的生态位。
三、横向速查表
维度 | setState | ValueNotifier | Provider | Riverpod ★ | Bloc/Cubit | GetX |
|---|---|---|---|---|---|---|
学习曲线 | ★☆☆ 最易 | ★★☆ | ★★☆ | ★★★☆ | ★★★★ | ★☆☆ 看起来易实则坑 |
跨组件共享 | ✗ | △ 手动 | ✅ | ✅ 原生 | ✅ | ✅ |
编译时安全 | - | - | ✗ runtime | ✅ | ✅ | ✗ runtime |
非 UI 层可读写 | ✗ | △ 全局变量式 | ✗ 要 context | ✅ ref 任意处 | ✅(bloc 本身是纯 Dart) | ⚠️ 全局单例 |
异步三态 | 手写 | 手写 | 手写 | ✅ AsyncValue | 手写/emit 多态 | 手写 |
精准重建 | ✗ 整棵 widget | ✅ | △ 需 Selector | ✅ watch 精确追踪 | ✅ BlocSelector | ✅ Obx |
测试友好 | ✗ 要 pump | △ | △ 要 pump | ✅ container override | ✅ bloc_test | ❌ 全局污染 |
适合规模 | 局部 | 1~2个共享值 | 小/中型旧栈 | 中大 / 大多数新项目 | 大型/强规范 | ⚠️ 短平快 |
四、选型决策树(照着套就行)
你的状态是不是只活在一个 Widget 内部? ├── 是 → setState / ValueNotifier → ✅ 别过度设计 └── 否(需要共享)→ 继续 ↓ 团队规模 & 业务复杂度? ├── 1~3人,快速原型 / MVP │ └── 想要低摩擦 → Riverpod(是的,新项目哪怕是小的也值得直接上) │ (Provider 也行但 Riverpod 迁移收益立刻兑现) ├── 正常商业 App(多数情况) │ └── ✅ Riverpod ——最佳性价比:轻量 + 编译安全 + 可长到很大 ├── 10+人 / 金融医疗政务 / 流程强审计需求 │ └── ✅ Bloc(或 Cubit 起步,逐步升) └── 已有 GetX 遗产 └── 稳住别急着重写;新模块用 Riverpod 写,逐步蚕食迁移五、最常见的坑(省你两小时调试)
坑 | 现象 | 修法 |
|---|---|---|
在 | 无限循环 | 永远不要 |
async 后 |
|
|
Provider 嵌套地狱 | 5 层 | 换 Riverpod(状态不再绑在树位置) |
| 编译/运行时怪错 |
|
滥用全局 | 内存一直涨 | 至少用 |
Riverpod | 字段变 → 整个 widget 重建 |
|
六、给你的下一步建议
如果你告诉我三件事,我可以帮你把架构骨架直接搭出来:
项目类型:电商 / 社交 / 工具 / 内部系统?
团队:你一个人还是有队友?队友 Flutter 熟练度?
当前阶段:从零新建 还是 已有项目想重构?
如果你想看的是 Riverpod 完整三层架构模板(models → repositories → providers → UI,带AsyncValue+SharedPreferences持久化 + 登录状态示例),我也可以直接给你一套可复制的文件结构。
❤️❤️❤️本人水平有限,如有纰漏,欢迎各位大佬评论批评指正!😄😄😄
💘💘💘如果觉得这篇文对你有帮助的话,也请给个点赞、收藏下吧,非常感谢!👍 👍 👍
🔥🔥🔥Stay Hungry Stay Foolish 道阻且长,行则将至,让我们一起加油吧!🌙🌙🌙