The preface
In flutter development, we use the Bloc framework for responsive development based on state changes. In this paper, Xiaohong disassembles and simplifies Bloc’s core business block, and talks about its realization idea. Bloc’s core capabilities are divided into the following two points:
- Add event
event
, convert ‘event stream’ to ‘state stream’state
- Listening to the
bloc
Every time flow,state
Status change, notificationwidget
update
Below, the method of defining Bloc is used to explain the construction of Bloc
1. Event Flow > State Flow (transit)
First, let’s simplify the Bloc code, and let’s see how Bloc converts a stream of events into a stream of states. The simplified code is as follows:
import 'dart:async';
abstract class ACubit<State> {
StreamController<State> _controller = StreamController<State>.broadcast();
State _state;
State get state => _state;
ACubit(this._state);
///Sends the State State to the stream
void emit(State state) {
if (_controller.isClosed) return;
if (state == _state) return;
_state = state;
_controller.add(_state);
}
///Provides method external listening State
StreamSubscription<State> listen(
void Function(State state) onData, {
Function onError,
void Function() onDone,
bool cancelOnError,
}) {
return _controller.stream.listen(
onData,
onError: onError,
onDone: onDone,
cancelOnError: cancelOnError,
);
}
Future<void> close() {
return_controller.close(); }}Copy the code
ACubit provides the most basic capabilities. Provide a listen method to externally listen for ‘State’ changes; The EMIT method is used to respond to state state changes.
abstract class ABloc<Event.State> extends ACubit<State> {
final _eventController = StreamController<Event>.broadcast();
ABloc(State initState) : super(initState) {
_bindEventToState();
}
///Send the event
void add(Event event) {
if (_eventController.isClosed) return;
_eventController.add(event);
}
///Need upper level implementation (convert event to state)
Stream<State> mapEventToState(Event event);
///Convert a stream of events to a stream of states
_bindEventToState() {
_eventController.stream
// asyncExpand Casts the stream content, resulting in a stream
.asyncExpand((event) => mapEventToState(event))
.listen((nextState) {
///The nextState is compared with the current state. After the comparison is successful, the nextState is put into the streamemit(nextState); }); }}Copy the code
ABloc is the base class we use directly. _bindEventToState is called in the constructor to convert the event stream to the state stream.
2. How to use BlocBuilder to monitor status changes in real time?
Xiaohong made a simplified explanation of the principle:
import 'package:flutter/material.dart';
import 'a_bloc.dart';
class BlocBuilder<T extends ACubit<S>, S> extends StatefulWidget {
final T cubit;
final Widget Function(BuildContext context, S state) builder;
const BlocBuilder({
Key key,
@required this.cubit,
@required this.builder,
}) : super(key: key);
@override
_BlocBuilderState<S> createState() => _BlocBuilderState<S>();
}
class _BlocBuilderState<S> extends State<BlocBuilder> {
void _update() {
setState(() {});
}
@override
void initState() {
///Listen for state changeswidget.cubit? .listen((_) { _update(); });super.initState();
}
@override
voiddispose() { widget.cubit? .close();super.dispose();
}
@override
Widget build(BuildContext context){
returnwidget.builder( context, widget.cubit.state, ); }}Copy the code
Encapsulation BlocBuilder
- The constructor passes in a custom bloc (inheritance
ABloc
),builder
Pass parameter is used to get each timestate
Notice of change.- in
initState
Init methodcubit
State listening, called directly for each state changesetState
Method to update the page
The following is an example of a call:
return BlocBuilder<CountBloc, CountState>(
cubit: CountBloc(CountState(1)),
builder: (context, state) {
returnContainer(... Omit business code)},)Copy the code
conclusion
Tripartite libraries such as Provider are referenced in BLOC library. Data sharing capabilities are implemented based on InheritedWidget. In this article, we only demonstrate the processing idea of Bloc core. Refer to Bloc source for details.
extension
The InheritedProvider implements data sharing Bloc simultaneously add twice and only responds to one problem processing