flutter中一切皆为Widget,因此在我们开发中,往往业务和UI逻辑写在一起,这样不利于代码维护,因此状态管理框架久诞生了,这篇就开始讲一讲Bloc。
对于Bloc库有两个,如下图:
flutter_bloc其实是对bloc的进一步封装,flutter_bloc引入了bloc库和provider库,是对bloc的进一步延伸。
bloc官方文档:https://bloclibrary.dev/#/zh-cn/coreconcepts
一.Bloc介绍
BLoC设计模式:BLoC模式的核心是Sink和Stream,它们用于处理输入和输出。通常,你会创建一个BLoC类,该类接收输入流并根据输入产生输出流。然后,UI组件订阅输出流以接收状态更新,并将用户操作发送到输入流。
Bloc有两种模式:
Bloc模式:该模式划分四层结构
bloc:逻辑层
state:数据层
event:所有的交互事件
view:页面
Cubit模式:该模式划分了三层结构
cubit:逻辑层
state:数据层
view:页面
Bloc模式和Cubit模式区别:
-
复杂度: BLoC:BLoC通常用于管理更复杂的业务逻辑和状态。它可以处理多个事件和多个状态,适用于大型、复杂的应用程序。
Cubit:Cubit的设计更简单,适用于处理较简单的状态和事件。它更适合于小型和中型应用程序,以及对状态管理模式不太熟悉的开发者。
-
事件和状态管理: BLoC:在BLoC中,事件和状态是分开管理的,你需要自己编写事件和状态的类,并在BLoC中进行映射。这使得BLoC更加灵活,但也更加复杂。
Cubit:Cubit将事件和状态合并到一个类中,称为Cubit类。这使得代码更加简洁,但在处理复杂的事件和状态时可能会变得混乱。
-
异步支持: BLoC:BLoC天生支持异步操作,可以轻松处理异步任务,例如网络请求。这是因为BLoC的mapEventToState方法可以返回Stream。
Cubit:Cubit也支持异步操作,但需要使用Emit函数来发射新的状态。
二.flutter_bloc简单使用
导入库:
dart
flutter_bloc: ^8.1.3
这是一个插件,可选择使用,简化模版代码生成。安装flutter_bloc插件
使用案例:计数器
dart
import 'package:flutter_bloc/flutter_bloc.dart';
// 定义事件
enum CounterEvent { increment, decrement }
class CounterBloc extends Bloc<CounterEvent, int> {
CounterBloc() : super(0);
@override
Stream<int> mapEventToState(CounterEvent event) async* {
switch (event) {
case CounterEvent.increment:
yield state + 1;
break;
case CounterEvent.decrement:
yield state - 1;
break;
}
}
}
在页面中使用 Bloc:
dart
import 'package:flutter/material.dart';
import 'package:flutter_bloc/flutter_bloc.dart';
class CounterPage extends StatelessWidget {
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text('Counter App'),
),
body: BlocProvider(
create: (context) => CounterBloc(),
child: CounterView(),
),
);
}
}
class CounterView extends StatelessWidget {
@override
Widget build(BuildContext context) {
final counterBloc = BlocProvider.of<CounterBloc>(context);
return Center(
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: [
BlocBuilder<CounterBloc, int>(
builder: (context, count) {
return Text('Count: $count', style: TextStyle(fontSize: 24));
},
),
SizedBox(height: 16),
Row(
mainAxisAlignment: MainAxisAlignment.center,
children: [
FloatingActionButton(
onPressed: () {
counterBloc.add(CounterEvent.increment);
},
child: Icon(Icons.add),
),
SizedBox(width: 16),
FloatingActionButton(
onPressed: () {
counterBloc.add(CounterEvent.decrement);
},
child: Icon(Icons.remove),
),
],
),
],
),
);
}
}
三.各种小部件
BlocBuilder
dart
BlocBuilder<BlocA, BlocAState>(
builder: (context, state) {
// return widget here based on BlocA's state
}
)
BlocBuilder是一个 Flutter 小部件,需要一个bloc和 一个builder函数。BlocBuilder处理构建小部件以响应新状态。BlocBuilder与 非常相似,StreamBuilder但具有更简单的 API,以减少所需的样板代码量。该builder函数可能会被多次调用,并且应该是一个纯函数,它返回一个小部件以响应状态。
BlocSelector
dart
BlocSelector<BlocA, BlocAState, SelectedState>(
selector: (state) {
// return selected state based on the provided state.
},
builder: (context, state) {
// return widget here based on the selected state.
},
)
BlocSelector是一个 Flutter 小部件,它类似于BlocBuilder但允许开发人员通过基于当前块状态选择新值来过滤更新。如果所选值不更改,则会阻止不必要的构建。所选值必须是不可变的,以便BlocSelector准确确定是否builder应该再次调用。
BlocListener
dart
BlocListener<BlocA, BlocAState>(
listener: (context, state) {
// do stuff here based on BlocA's state
},
child: Container(),
)
BlocListener是一个 Flutter 小部件,它采用BlocWidgetListener和 一个可选参数bloc,并调用listener来响应块中的状态变化。它应该用于每次状态更改需要发生一次的功能,例如导航、显示 a SnackBar、显示 aDialog等...