Flutter 状态管理终极指南:Provider vs Riverpod vs Bloc(附实战对比)
·
一、引言
在 Flutter 开发中,状态管理(State Management) 是绕不开的核心话题。随着应用复杂度提升,简单的 setState 已无法满足需求。目前主流方案包括 Provider、Riverpod、Bloc 等。本文将通过一个“待办事项(Todo)”应用,对比三种方案的写法、性能与适用场景,并给出选型建议。
二、为什么需要状态管理?
- 避免组件间频繁传递回调
- 实现数据共享与响应式更新
- 提升代码可维护性与可测试性
图:无状态管理 vs 有状态管理的数据流对比
三、方案一:Provider(官方推荐入门方案)
✅ 优点:
- 官方支持,学习曲线平缓
- 基于 InheritedWidget,性能良好
📦 添加依赖(pubspec.yaml):
dependencies:
flutter:
sdk: flutter
provider: ^6.1.0
💡 示例代码(Todo 列表):编辑
// todo_model.dart
class Todo {
final String title;
bool completed;
Todo(this.title, {this.completed = false});
}
// todo_provider.dart
class TodoProvider with ChangeNotifier {
final List<Todo> _todos = [];
List<Todo> get todos => _todos;
void addTodo(String title) {
_todos.add(Todo(title));
notifyListeners();
}
void toggle(int index) {
_todos[index].completed = !_todos[index].completed;
notifyListeners();
}
}
// main.dart
void main() {
runApp(
ChangeNotifierProvider(
create: (_) => TodoProvider(),
child: const MyApp(),
),
);
}
// 在 UI 中使用
Consumer<TodoProvider>(
builder: (context, todoProvider, child) {
return ListView.builder(
itemCount: todoProvider.todos.length,
itemBuilder: (context, i) => CheckboxListTile(
title: Text(todoProvider.todos[i].title),
value: todoProvider.todos[i].completed,
onChanged: (_) => todoProvider.toggle(i),
),
);
},
)
四、方案二:Riverpod(Provider 的现代化升级)
✅ 优点:
- 不依赖
BuildContext - 支持编译时安全、异步状态、组合 Provider
- 更适合大型项目
📦 依赖:
dependencies:
flutter_riverpod: ^2.5.0
💡 示例代码:
final todoProvider = StateNotifierProvider<TodoNotifier, List<Todo>>((ref) {
return TodoNotifier();
});
class TodoNotifier extends StateNotifier<List<Todo>> {
TodoNotifier() : super([]);
void add(String title) {
state = [...state, Todo(title)];
}
void toggle(int index) {
state = [
for (int i = 0; i < state.length; i++)
if (i == index)
Todo(state[i].title, completed: !state[i].completed)
else
state[i]
];
}
}
// UI 中使用(无需 Consumer)
@override
Widget build(BuildContext context, WidgetRef ref) {
final todos = ref.watch(todoProvider);
return ListView.builder(
itemCount: todos.length,
itemBuilder: (context, i) => CheckboxListTile(
title: Text(todos[i].title),
value: todos[i].completed,
onChanged: (_) => ref.read(todoProvider.notifier).toggle(i),
),
);
}
✅ 优势:即使在
showDialog或静态方法中也能访问状态!
五、方案三:Bloc(事件驱动,适合复杂业务)
✅ 优点:
- 清晰分离逻辑与 UI
- 强类型、可测试性强
- 适合金融、电商等高复杂度场景
📦 依赖:
dependencies:
flutter_bloc: ^8.1.0
💡 核心结构:
- Event:用户操作(如 AddTodo)
- Bloc:处理逻辑
- State:UI 状态(如 Loading / Success)
// todo_bloc.dart
class TodoBloc extends Bloc<TodoEvent, TodoState> {
final List<Todo> _todos = [];
TodoBloc() : super(TodoInitial()) {
on<AddTodo>((event, emit) {
_todos.add(Todo(event.title));
emit(TodoLoaded(_todos));
});
}
}
⚠️ 编写量较大,但逻辑极其清晰。
六、三大方案对比总结
| 方案 | 学习成本 | 适用场景 | 是否依赖 Context | 异步支持 |
|---|---|---|---|---|
| Provider | 低 | 中小型项目 | 是 | 一般 |
| Riverpod | 中 | 中大型项目 | 否 ✅ | 强 |
| Bloc | 高 | 复杂业务/团队协作 | 否 | 极强 |
七、结语
- 新手推荐:从 Provider 入手
- 进阶项目:优先考虑 Riverpod
- 企业级应用:Bloc + Clean Architecture
GitHub 示例仓库:github.com/yourname/flutter-state-compare
欢迎在评论区讨论你用的状态管理方案!
更多推荐


所有评论(0)