BLoC (Business Logic Component) 是 Flutter 中一种流行的状态管理架构,它可以帮助你将业务逻辑与 UI 分离,使代码更清晰、可测试性更强。
核心概念
1. BloC 的核心组件
- Events:用户交互或系统事件(如按钮点击、网络请求完成)
- States:应用的状态表示(如加载中、数据加载成功、错误)
- Bloc:处理事件并发出新状态的业务逻辑组件
2. 数据流
UI → Event → BloC → State → UI
基础实现步骤
1. 添加依赖
在 pubspec.yaml
中添加:
yaml
dependencies:
flutter_bloc: ^8.1.3
bloc: ^8.1.2
运行 flutter pub get
2. 创建基本结构
定义事件 (Events)
dart
// counter_event.dart
abstract class CounterEvent {}
class IncrementEvent extends CounterEvent {}
class DecrementEvent extends CounterEvent {}
定义状态 (States)
dart
// counter_state.dart
class CounterState {
final int count;
CounterState(this.count);
}
创建 BloC
dart
// counter_bloc.dart
import 'package:bloc/bloc.dart';
class CounterBloc extends Bloc<CounterEvent, CounterState> {
CounterBloc() : super(CounterState(0)) {
on<IncrementEvent>((event, emit) {
emit(CounterState(state.count + 1));
});
on<DecrementEvent>((event, emit) {
emit(CounterState(state.count - 1));
});
}
}
3. 在 UI 中使用
dart
// main.dart
import 'package:flutter/material.dart';
import 'package:flutter_bloc/flutter_bloc.dart';
void main() {
runApp(MyApp());
}
class MyApp extends StatelessWidget {
@override
Widget build(BuildContext context) {
return MaterialApp(
home: BlocProvider(
create: (context) => CounterBloc(),
child: CounterPage(),
),
);
}
}
class CounterPage extends StatelessWidget {
@override
Widget build(BuildContext context) {
final counterBloc = BlocProvider.of<CounterBloc>(context);
return Scaffold(
appBar: AppBar(title: Text('BLoC Counter')),
body: Center(
child: BlocBuilder<CounterBloc, CounterState>(
builder: (context, state) {
return Text(
'Count: ${state.count}',
style: TextStyle(fontSize: 24),
);
},
),
),
floatingActionButton: Column(
mainAxisAlignment: MainAxisAlignment.end,
children: [
FloatingActionButton(
onPressed: () => counterBloc.add(IncrementEvent()),
child: Icon(Icons.add),
),
SizedBox(height: 10),
FloatingActionButton(
onPressed: () => counterBloc.add(DecrementEvent()),
child: Icon(Icons.remove),
),
],
),
);
}
}
进阶用法
1. 处理异步操作
dart
// 在 BloC 中处理异步事件
on<LoadDataEvent>((event, emit) async {
emit(LoadingState());
try {
final data = await repository.fetchData();
emit(DataLoadedState(data));
} catch (e) {
emit(ErrorState(e.toString()));
}
});
2. 使用 BlocObserver 调试
dart
void main() {
Bloc.observer = SimpleBlocObserver();
runApp(MyApp());
}
class SimpleBlocObserver extends BlocObserver {
@override
void onChange(BlocBase bloc, Change change) {
super.onChange(bloc, change);
print('${bloc.runtimeType} $change');
}
}
3. 多个 BloC 的使用
dart
return MultiBlocProvider(
providers: [
BlocProvider<CounterBloc>(create: (context) => CounterBloc()),
BlocProvider<ThemeBloc>(create: (context) => ThemeBloc()),
],
child: MyApp(),
);
最佳实践
- 保持 BloC 简单:每个 BloC 应该只关注单一功能
- 避免在 BloC 中直接使用 BuildContext
- 使用 freezed 或 equatable 来简化状态和事件的比较
- 编写单元测试:BLoC 很容易测试,因为它是纯 Dart 代码
项目结构建议
lib/
features/
feature_name/
bloc/
feature_bloc.dart
feature_event.dart
feature_state.dart
views/
feature_page.dart
widgets/
feature_widget.dart
repositories/
feature_repository.dart
main.dart
BLoC 架构可以帮助你构建可维护、可测试的 Flutter 应用。开始时可能会觉得有些复杂,但随着使用会越来越顺手。