状态管理概览:从 setState 到 InheritedWidget
easyflutterstate-managementsetstateinheritedwidgetephemeral-state
状态的分类
Flutter 官方将应用状态分为两类:
短暂状态(Ephemeral State):只属于单个 Widget 的 UI 状态,不需要共享。如:TabBar 当前选中的 Tab、Animation 当前进度、表单输入框的内容。用 setState 管理即可。
应用状态(App State):需要跨 Widget 共享,且在导航时需要持久化。如:登录用户信息、购物车、用户设置。需要状态管理方案。
setState —— 从简开始
setState 是 Flutter 自带的最基础状态管理:
class CounterPage extends StatefulWidget {
@override
State<CounterPage> createState() => _CounterPageState();
}
class _CounterPageState extends State<CounterPage> {
int _count = 0;
void _increment() => setState(() => _count++);
@override
Widget build(BuildContext context) {
return Scaffold(
body: Center(child: Text('$_count')),
floatingActionButton: FloatingActionButton(
onPressed: _increment,
child: const Icon(Icons.add),
),
);
}
}
适合场景:单个 Widget、状态不需要被外部访问、生命周期与 Widget 一致。
不适合场景:多个页面共享状态、深层嵌套传参(prop drilling)。
InheritedWidget —— 内置跨层传递
当多个 Widget 需要同一状态时,InheritedWidget 提供了高效的跨层传递(详见「BuildContext 与 InheritedWidget」一章):
AppState (InheritedWidget)
↓ 持有 counter = 5
┌──────────┴──────────┐
PageA PageB (Counter.of(context) = 5)
InheritedWidget 是所有第三方状态管理库的基础,但直接使用它需要较多样板代码。
主流状态管理方案对比
| 方案 | 学习曲线 | 样板代码 | 适合规模 | 特点 |
|---|---|---|---|---|
| setState | 极低 | 无 | 小型 | 内置,够用就用 |
| InheritedWidget | 中 | 较多 | 中小 | 底层机制 |
| Provider | 低 | 少 | 中大 | 对 InheritedWidget 的封装 |
| Riverpod | 中 | 少 | 中大 | Provider 的进化版,编译时安全 |
| BLoC/Cubit | 高 | 较多 | 大型 | 强业务逻辑分离,适合复杂场景 |
| GetX | 低 | 极少 | 中 | 全家桶,争议较多 |
选型建议
- 简单页面:
setState - 中等复杂度、团队有 Provider 经验:
Provider/flutter_blocCubit - 追求类型安全、代码生成、测试友好:
Riverpod - 大型应用、严格分层架构:
BLoC - 快速原型、单人项目:
GetX(不推荐在大型团队使用,混入太多功能)
建议:不要在项目中混用多种状态管理方案(除非有明确的模块化边界)。