【Flutter 必备插件】状态管理 flutter_bloc_flutter 最新状态管理
flutter_bloc 是基于 BLoC(Business Logic Component)模式的 Flutter 状态管理库,它封装了 bloc package,帮助我们更清晰地组织业务逻辑与 UI 的分离。核心思想是事件驱动 和 状态响应。
核心概念
- Event(事件):用户的输入或其他外部触发,比如按钮点击。
- State(状态):界面状态的表现,比如加载中、成功、失败。
- Bloc(逻辑组件):接收事件 -> 处理逻辑 -> 发出新状态。
流程图如下:
UI → Bloc.add(Event) → Bloc → emit(State) → UI rebuild
实战:以登录流程为例
1. 封装数据层
class UserService { static Future smsLoginCode(String mobile) async { final response = await HttpUtil().post(\'/api/sms/sendLoginCode\', data: { \'mobile\': mobile,} ); return ApiResponse.fromJson(response, null); } static Future<ApiResponse> loginCode(String mobile, String passWord) async { final response = await HttpUtil().post(\'/api/smsLogin\', data: { \'passWord\': passWord, \'userName\': mobile} ); return ApiResponse.fromJson(response, (json) => Token.fromJson(json)); }}
2. 封装 BLoc(逻辑层)
1.定义 Event
part of \'login_bloc.dart\';abstract class LoginEvent {}class PhoneSmsLogin extends LoginEvent { PhoneSmsLogin({ required this.phone, required this.smsCode}); final String phone; final String smsCode;}
2.定义 State
part of \'login_bloc.dart\';abstract class LoginState {}class LoginInitial extends LoginState {}class LoginLoading extends LoginState {}class LoginSuccess extends LoginState {}class LoginFailure extends LoginState {}
3.实现 BLoC
part \'login_event.dart\';part \'login_state.dart\';class LoginBloc extends Bloc { LoginBloc() : super(LoginInitial()) { on((event, emit) async { emit(LoginLoading()); ApiResponse token = await UserService.loginCode(event.phone, event.smsCode); UserStorage.setToken(token.data!); emit(LoginSuccess()); }); }}
- UI 层使用 BLoC(展示层)
main.dart
runApp( MultiBlocProvider( providers: [ BlocProvider(create: (context) => LoginBloc()), ], child: const App() ) );
登录页
@override Widget build(BuildContext context) { return Scaffold( backgroundColor: Colors.white, appBar: AppBar( forceMaterialTransparency: true, toolbarHeight: 0, ), body: BlocProvider.value( value: context.read(), child: BlocConsumer( builder: (context, state) { // if (state is LoginLoading) { // return Center(child: Text(\"正在请求服务器\"),); // } return Container( alignment: Alignment.center, margin: const EdgeInsets.only(top: 50.0), child: Column( children: [ _logo(), _phone(), _sms(), _loginBtn(), ], ), ); }, listener: (context, state) { if (state is LoginLoading) { } else if (state is LoginSuccess) { GoRouterUtil.pop(context); } else if (state is LoginFailure) { } } ), ), ); }