Flutter状态管理神器Bloc全解析:从入门到实战(一)
·
在Flutter开发中,状态管理始终是架构设计的核心问题。随着项目复杂度提升,如何优雅地管理数据流、实现UI与逻辑解耦?Bloc和Cubit作为Flutter官方推荐的状态管理方案,凭借清晰的架构设计和可预测的状态流脱颖而出。
- Bloc:通过事件驱动状态变更,适合需要追踪操作来源的复杂场景
- Cubit:简化版Bloc,通过方法直接触发变更,适合轻量级场景
一、快速安装
flutter pub add flutter_bloc
二、Cubit计数器示例使用理解
2.1 Cubit方式定义以及使用
// counter_cubit.dart
// 定义一个存储计数器的cubit 状态是 int类型的
import 'package:flutter_bloc/flutter_bloc.dart';
class CounterCubit extends Cubit<int> {
CounterCubit() : super(0);
// 提供外界修改状态的函数
void increment() {
emit(state + 1);
}
void decrement() {
emit(state - 1);
}
}
代码解读:
- 继承
Cubit<int>指定状态类型为int emit()方法触发状态更新- 业务逻辑完全封装在Cubit内部
2.2 Cubit 状态的获取以及修改
class TestPage extends StatelessWidget {
const TestPage({super.key});
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
backgroundColor: Theme.of(context).colorScheme.inversePrimary,
title: Text("cubit"),
),
body: BlocProvider(
create: (_) => CounterCubit(),
child: ShowPage())
);
}
}
class ShowPage extends StatelessWidget {
const ShowPage({super.key});
Widget build(BuildContext context) {
return Column(children: [
BlocBuilder<CounterCubit, int>(
builder: (context, state) {
return Text(
"number: $state",
style: Theme.of(context).textTheme.headlineMedium,
);
},
),
TextButton(onPressed: () {
// 利用上下文获取状态数据中提供的方法改变数据
context.read<CounterCubit>().increment();
}, child: Text("add")),
TextButton(onPressed: () {
context.read<CounterCubit>().decrement();
}, child: Text("sub"))
],);
}
}
关键技术点:
BlocProvider:将某个状态数据提供给某个组件使用BlocBuilder:获取状态数据提供组件渲染使用的
3.3 Cubit方式监听状态的变化
- 方式一:在Cubit中重写onChange方法
class CounterCubit extends Cubit<int> {
CounterCubit() : super(0);
void increment() {
emit(state + 1);
}
void decrement() {
emit(state - 1);
}
void onChange(Change<int> change) {
// 当状态改变时候,会调用改方法
debugPrint("***** CounterCubit onChange $change");
super.onChange(change);
}
}
- 方式二:创建BlocObserver重写onChange方法
// 创建BlocObserver
import 'package:bloc/bloc.dart';
import 'package:flutter/foundation.dart';
class CounterObserver extends BlocObserver {
const CounterObserver();
void onChange(BlocBase<dynamic> bloc, Change<dynamic> change) {
super.onChange(bloc, change);
debugPrint('CounterObserver --- ${bloc.runtimeType} $change');
}
}
// 使用BlocObserver
class ShowPage extends StatelessWidget {
const ShowPage({super.key});
Widget build(BuildContext context) {
// 演示在这里设置监听
Bloc.observer = CounterObserver();
return Column(children: [
BlocBuilder<CounterCubit, int>(
builder: (context, state) {
return Text(
"number: $state",
style: Theme.of(context).textTheme.headlineMedium,
);
},
),
TextButton(onPressed: () {
context.read<CounterCubit>().increment();
}, child: Text("add")),
TextButton(onPressed: () {
context.read<CounterCubit>().decrement();
}, child: Text("sub"))
],);
}
}
三、Bloc计数器示例使用理解
3.1 Bloc方式定义以及使用
// counter_bloc.dart 定义
import 'package:flutter/foundation.dart';
import 'package:flutter_bloc/flutter_bloc.dart';
sealed class CounterEvent {}
// 定义event事件
final class CounterIncrementPressed extends CounterEvent {}
final class CounterDecrementPressed extends CounterEvent {}
class CounterBloc extends Bloc<CounterEvent, int> {
CounterBloc() : super(0) {
// 对应event事件的处理
on<CounterIncrementPressed>((event, emit) {
debugPrint("CounterBloc");
emit(state + 1);
});
on<CounterDecrementPressed>((event, emit) {
emit(state - 1);
});
}
}
设计优势:
- 明确的事件-状态映射关系
- 支持异步操作和复杂事件处理
- 完整的操作历史追溯能力
3.2 Bloc 状态的获取以及修改
class TestPage extends StatelessWidget {
const TestPage({super.key});
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
backgroundColor: Theme.of(context).colorScheme.inversePrimary,
title: Text("bloc"),
),
body: BlocProvider(
create: (_) => CounterBloc(),
child: ShowPage())
);
}
}
class ShowPage extends StatelessWidget {
const ShowPage({super.key});
Widget build(BuildContext context) {
return Column(children: [
BlocBuilder<CounterBloc, int>(
builder: (context, state) {
return Text(
"number: $state",
style: Theme.of(context).textTheme.headlineMedium,
);
},
),
TextButton(onPressed: () {
// 发送event事件
context.read<CounterBloc>().add(CounterIncrementPressed());
}, child: Text("add")),
TextButton(onPressed: () {
context.read<CounterBloc>().add(CounterDecrementPressed());
}, child: Text("sub"))
],);
}
}
四、Cubit和Bloc的优缺点
| 特性 | Cubit | Bloc |
|---|---|---|
| 代码复杂度 | ⭐️⭐️⭐️⭐️⭐️(简单) | ⭐️⭐️⭐️(中等) |
| 事件追溯能力 | ❌ | ⭐️⭐️⭐️⭐️⭐️ |
| 学习曲线 | 平缓 | 较陡 |
| 适合场景 | 简单状态管理 | 复杂业务逻辑 |
| 测试便利性 | 简单 | 需要模拟事件 |
根据Cubit和Bloc上面的使用情况以及对官方文档的阅读理解
Cubit相对于Bloc模板代码量更少,只需要定义状态以及修改状态的函数,更容易理解
Bloc则需要定义状态、event事件、处理event事件的操作等,相对于Cubit的优势是能了解状态的变化以及触发状态变化的原因event。
选型建议:
- 小型项目/简单状态 → Cubit
- 中大型项目/需要事件溯源 → Bloc
- 渐进式迁移:从Cubit开始,必要时升级Bloc
更多推荐

所有评论(0)