The provider state management tool has been tried before, which is simple and convenient. However, in the new project, the relevant students used the Bloc status management tool, and had a brief understanding of Stream knowledge some time ago, so they took the opportunity to learn the basic contents related to Bloc.
Bloc
Bloc separates styling from business logic, making development easier, reusability better, and testing easier.
The following concepts should be understood in advance before using Bloc;
Event
Event events are input to Bloc, typically added in response to user interactions (such as button presses) or lifecycle events (such as page loads). Event classes can be defined using an enumeration type, and for relatively complex events can be defined as class by the federated business.
enum TestEvent { onEvent1, onEvent2 ... onEventN}
Copy the code
States
States state is the output of Bloc, generally used for UI status update, page update drawing, etc. It is generally necessary to define different data types to represent changes in data state;
class TestState { final int state1; final String state2; . final User stateN; TestState(this.state1, this.state2 ... this.stateN); }Copy the code
Transitions
A transition from one state to the next. Transitions consist of the current state, events, and the next state; For example, state changes in each onEvent in the TestEvent defined above can be considered Transitions; OnTransition is called before the state update of the Bloc. It is often used for Bloc logging and analysis.
@override
void onTransition(Transition<NumberEvent, int> transition) {
print('====onTransition===${transition}');
super.onTransition(transition);
}
Copy the code
Streams
As asynchronous data transmission; Async * can use the yield keyword and return a Stream;
Stream<int> testStream(int max) async* { for (int i = 0; i < max; i++) { yield i; }}Copy the code
Blocs
Bloc is the state that converts the Event Event of Stream input into the output. Each custom Bloc must inherit from the underlying Bloc; By copying initialState and mapEventToState methods to complete the Event and State State transition; InitialState indicates the initialization state of Bloc. This state is the state before receiving any event. MapEventToState takes Event as a parameter and returns the Stream state. The current block state can be accessed at any time through the state attribute. Each Bloc has an Add method to add new events to mapEventToState. Bloc obtains abnormal information through onError method and handles it.
class TestBloc extends Bloc<TestEvent, int> { @override int get initialState => 0; @override Stream<int> mapEventToState(TestEvent event) async* { switch (event) { case TestEvent.onEvent1: yield state - 1; break; case TestEvent.onEvent2: yield state + 1; break; } } @override void onError(Object error, StackTrace stackTrace) { print('====onError===$error, $stackTrace'); super.onError(error, stackTrace); }}Copy the code
BlocDelegate
BlocDelegate is a delegate for Bloc. It can manage onTransition and onError globally or in the scope required.
class NumberBlocDelegate extends BlocDelegate { @override void onEvent(Bloc bloc, Object event) { print('====Delegate.onEvent===$bloc====$event'); super.onEvent(bloc, event); } @override void onTransition(Bloc bloc, Transition transition) { print('====Delegate.onTransition===$bloc====$transition'); super.onTransition(bloc, transition); } @override void onError(Bloc bloc, Object error, StackTrace stackTrace) { print('====Delegate.onError===$error, $stackTrace'); super.onError(bloc, error, stackTrace); }}Copy the code
TestCode
In the next section, I will try to update the data using FlutterBloc. In the next section, I will try to update the data using FlutterBloc.
import 'package:bloc/bloc.dart'; import 'package:flutter/material.dart'; class BlocPage extends StatefulWidget { @override State<StatefulWidget> createState() => _BlocPageState(); } class _BlocPageState extends State<BlocPage> { var _number = 0; NumberBloc _bloc = NumberBloc(); @override Widget build(BuildContext context) { return Scaffold( appBar: AppBar(title: Text('Bloc Page')), body: Center(child: Text(' current Number = $_number\n next Number = ${_bloc. State}', style: TextStyle(fontSize: 20.0, color: Colors.blue))), floatingActionButton: FloatingActionButton( child: Icon(Icons.add), onPressed: () { _bloc.add(NumberEvent.addEvent); setState(() => _number = _bloc.state); })); } } enum NumberEvent { addEvent } class NumberBloc extends Bloc<NumberEvent, int> { @override int get initialState => 10; @override Stream<int> mapEventToState(NumberEvent event) async* { switch (event) { case NumberEvent.addEvent: yield state + 5; break; } } @override void onTransition(Transition<NumberEvent, int> transition) { print('====onTransition===${transition}'); super.onTransition(transition); } @override void onError(Object error, StackTrace stackTrace) { print('====onError===$error, $stackTrace'); super.onError(error, stackTrace); }}Copy the code
After experiencing Bloc, the initial feeling is slightly more complicated than Provider, but the division of labor is more clear. In the next section, I will try FlutterBloc’s UI data update and so on. If there is any mistake, please give guidance!
Source: Young Monk Atze