携手创造,共同生长!这是我参加「日新方案 8 月更文应战」的第18天,点击查看活动概况
本文首要介绍下Bloc的运用和介绍以及和Cubit的差异
之前咱们介绍了运用Cubit来处理数据,那么Bloc呢?
1. Bloc
Bloc比较Cubit是一个更高的类,Cubit咱们知道经过揭露触发状改变的函数。而Bloc依靠事情来床触发状况的改动,Bloc页拓宽了BlocBase,一切和Cubit的API也是相似。Blocs不是在Bloc上调用函数然后直接宣布一个新的状况,而是经过接收事情而且将传入的事情转化为状况输出。
abstract class CounterExampleEvent{}
class AddEvent extends CounterExampleEvent {
}
class ReduceEvent extends CounterExampleEvent {
}
class CounterExampleBloc extends Bloc<CounterExampleEvent, int> {
CounterExampleBloc() : super(0)
}
2. 状况改动
咱们实现逻辑,经过咱们的Event驱动
class CounterExampleBloc extends Bloc<CounterExampleEvent, int> {
CounterExampleBloc() : super(0) {
on<AddEvent>((event, emit) {
emit(state+1);
});
on<ReduceEvent>((event, emit) {
// TODO: implement event handler
state-1;
emit(state-1);
});
}
}
Bloc要求咱们经过on<Event>上注册事情处理程序 API, 而不是在Cubit中的功用. 事情处理程序负责将任何传入事情转换为零或多个传出状况.更新EventHandler来处理AddEvent事情.
事情咱们能够经过stategetter 方法拜访 bloc 的当时状况和经过emit(state + 1)改动状况.
3. 运用
咱们运用BlocProvider进行初始化
class CounterExamplePage extends StatelessWidget {
@override
Widget build(BuildContext context) {
return BlocProvider(
create: (BuildContext context) => CounterExampleBloc(),
child: Builder(builder: (context) => _buildPage(context)),
);
}
}
经过获取bloc 后对事情行为进行传入事情, bloc.add(AddEvent()),因为Bloc类承继了BlocBase,因而咱们能够随时经过stategetter 来拜访bloc的当时状况,就像运用 Cubit 相同。
Widget _buildPage(BuildContext context) {
final bloc = BlocProvider.of<CounterExampleBloc>(context);
return Scaffold(
appBar: AppBar(title: const Text('Bloc-Blocw范例')),
body: Center(
child: BlocBuilder<CounterExampleBloc, int>(
builder: (context, state) {
return Text(
'点击了 ${bloc.state} 次',
style: const TextStyle(fontSize: 30.0),
);
},
),
),
floatingActionButton: FloatingActionButton(
onPressed: () => bloc.add(AddEvent()),
child: const Icon(Icons.add),
),
);
}
4. Stream运用
就像Cubit相同,Bloc是Stream的一种特殊类型,这意味着咱们还能够订阅Bloc来实时更新其状况:
Widget _buildPage(BuildContext context) {
final bloc = BlocProvider.of<CounterExampleBloc>(context);
int count = 0;
bloc.stream.listen((event) { count = event*2;});
return Scaffold(
appBar: AppBar(title: const Text('Bloc-Counter范例')),
body: Center(
child: BlocBuilder<CounterExampleBloc, int>(
builder: (context, state) {
return Text(
'点击了 $count 次',
style: const TextStyle(fontSize: 30.0),
);
},
),
),
}
咱们经过监听能够处理咱们 自界说数据,当咱们不想再接收更新时,在订阅上调用cancel,并封闭Bloc。
5. 观察
因为一切Bloc都扩展了BlocBase,因而咱们能够运用onChange观察Bloc的一切状况改变。
@override
void onChange(Change<int> change) {
super.onChange(change);
print(change);
}
- onTransition
Bloc和Cubit之间的首要差异因素是,因为Bloc是事情驱动的,因而咱们也能够捕获有关触发状况更改的信息。
咱们能够经过重写onTransition来做到这一点。
@override
void onTransition(Transition<CounterExampleEvent, int> transition) {
super.onTransition(transition);
print(transition);
}

onTransition在onChange之前被调用,而且包括触发从currentState到nextState改动的事情。
6. 观察者
咱们能够在自界说BlocObserver中重写 onTransition,以观察从一个方位发生的一切过渡。
class TestBlocObserver extends BlocObserver{
@override
void onChange(BlocBase bloc, Change change) {
super.onChange(bloc, change);
print('${bloc.runtimeType} $change');
}
@override
void onTransition(Bloc bloc, Transition transition) {
super.onTransition(bloc, transition);
print('${bloc.runtimeType} $transition');
}
@override
void onError(BlocBase bloc, Object error, StackTrace stackTrace) {
print('${bloc.runtimeType} $error $stackTrace');
super.onError(bloc, error, stackTrace);
}
}
运用的时候和Cubit相似,CounterExampleBloc初始化之前添加观察者
Bloc.observer = TestBlocObserver();
打印成果
首要调用onTransition(在大局之前先于本地),然后调用onChangeBloc实例的另一个独特功用是,它们使咱们能够重写onEvent,不管何时将新事情添加到Bloc都会调用onEvent。就像onChange和onTransition相同,onEvent能够在本地或大局重写。
@override
void onEvent(CounterExampleEvent event) {
super.onEvent(event);
print(event);
}
在BlocObserver类中
@override
void onEvent(Bloc bloc, Object? event) {
super.onEvent(bloc, event);
print('${bloc.runtimeType} $event');
}
就会调用onEvent。本地onEvent在BlocObserver中的大局onEvent之后被调用。
7. Cubit和Bloc
简单逻辑运用Cubit。
运用Cubit的最大长处之一便是简单。当创建一个Cubit时,咱们只需要界说状况以及咱们想要揭露的改动状况的函数即可。比较之下,创建Bloc时,咱们有必要界说状况、事情和EventHandler实现。这使得Cubit更简单了解,而且触及的代码更少。
关于一些复杂情况运用Bloc。
运用Bloc的最大优势之一便是知道状况改变的顺序以及触发这些改变的切当原因。关于关于应用程序功用至关重要的状况,运用更多事情驱动的方法来捕获状况改变之外的一切事情可能会十分有益。




