preface

Recently, Xiao Hong was involved in Dart 2.0 air safety upgrades for the Company’s Flutter project. We upgraded all the tripartite libraries we relied on, including Bloc. As a highly used state management framework, Bloc underwent a few structural and detailed optimizations in the release iteration. The following is a summary of the use of the new version of Bloc.

use

The Bloc version used by the Bomb is as follows

flutter_bloc: ^7.31.
Copy the code

Learn new things by using simple examples

  • Create a page with add and subtract actions, using Bloc to manipulate the increment and decrement event.
class _TestBlocPageState extends State<TestBlocPage> {
  late TestDartBloc _bloc;

  @override
  void initState() {
    super.initState();
    _bloc = TestDartBloc(TestDartState(0));
  }

  @override
  Widget build(BuildContext context) {
    return BlocBuilder<TestDartBloc, TestDartState>(
      bloc: _bloc,
      builder: (context, state) {
        return Column(
          children: [
            // Displays the current numeric result
            Text(state.num.toString()),
            TextButton(
                onPressed: () {
                  // Perform the increment operation
                  _bloc.add(IncreaseEvent());
                },
                child: Text('add')),
            TextButton(
                onPressed: () {
                  // Perform the decrement operation
                  _bloc.add(ReduceEvent());
                },
                child: Text('reduce')),,); }); }}Copy the code

State and event models in Bloc are defined as follows

part of 'test_dart_bloc.dart';
/// Bloc state
class TestDartState {
  int num = 0;
  TestDartState(this.num);
}
Copy the code
part of 'test_dart_bloc.dart';
/// Bloc event
@immutable
abstract class TestDartEvent {}
// Add events
class IncreaseEvent extends TestDartEvent{}
// Decrement events
class ReduceEvent extends TestDartEvent{}
Copy the code

Bloc is created and mapEventToState is overridden to receive the state flow of event flow

import 'dart:async';
import 'package:flutter_bloc/flutter_bloc.dart';
part 'test_dart_event.dart';
part 'test_dart_state.dart';

class TestDartBloc extends Bloc<TestDartEvent.TestDartState> {
  TestDartBloc(TestDartState state) : super(state);

  @override
  Stream<TestDartState> mapEventToState(TestDartEvent event) async* {
    if (event is IncreaseEvent) {
      await Future.delayed(Duration(seconds: 10));
      yield TestDartState(state.num + 1);
    } else if (event is ReduceEvent) {
      yield TestDartState(state.num - 1); }}}Copy the code

Ok, just run the code above and our demo will be up and running. However, the above writing method is completely consistent with the low version of Bloc. After the high version iteration, what optimization has Bloc made?

Bloc new form

The use of mapEventToState has been deprecated and will be completely removed in a future version

  /// **@Deprecated - Use on<Event>Will be removed in V8.0.0 **
  ///
  /// Must be implemented when a class extends [Bloc].
  /// [mapEventToState] is called whenever an [event] is [add]ed
  /// and is responsible for converting that [event] into a new [state].
  /// [mapEventToState] can `yield` zero, one, or multiple states for an event.
  @Deprecated('Use on
      
        instead. Will be removed in V8.0.0 '
      )
  Stream<State> mapEventToState(Event event) async* {}
Copy the code

The new usage recommends using on for event registration. We rewrite bloc in the demo above:

class TestDartBloc extends Bloc<TestDartEvent.TestDartState> {
  TestDartBloc(TestDartState state) : super(state) {
    init();
  }
  void init() {
    on<IncreaseEvent>((event, emit) async {
      await Future.delayed(Duration(seconds: 10));
      emit(TestDartState(state.num + 1));
    });

    on<ReduceEvent>((event, emit) {
      state.num - 1; emit(state); }); }}Copy the code

Replace the code after running demo, direct success.

The blocking property of the event queue?

Currently, the latest version of Bloc supports both on and mapEventToState. Is there any practical difference between the two methods?

Xiao Hong summarized an article on the queue properties of Bloc Events when using the old version (before air safety) Bloc.

In the mapEventToState method of Bloc, the event queue is a blocking queue, first-in, first-out, and only after the consumption of the previous event, the next event in the queue will be responded.

As shown in Demo (mapEventToState mode), the simulation of the increment event takes 10 seconds. When the increment and decrement buttons are clicked successively, due to the blocking feature of the event queue, the increment event will be consumed for 10 seconds before the deceleration event is responded by mapEventToState.

So, does this feature still exist after the new iteration of Bloc? In the latest version of Bloc, Xiaohong’s demo tests concluded that:

  • When event capture is done using mapEventToState, the event queue remains blocking.
  • When on is used to register listeners, the event queue is asynchronous, non-blocking and non-interfering by default. If bloc is used as an event bus, Xiaohong thinks an asynchronous non-blocking design is more reasonable.

Q: What if you want to register using on and still want the event queue to ensure sequential execution and thus keep the blocking feature? Answer: Use custom Transformer to implement event synchronization queues.

    on<IncreaseEvent>((event, emit) async {
      await Future.delayed(Duration(seconds: 10));
      emit(TestDartState(state.num + 1));
    },
    transformer: (events, mapper) => events.asyncExpand(mapper),
);
Copy the code

Pub. dev/packages/bl…

About the source code analysis of the latest version Bloc, Xiaohong will sort out and summarize in the next chapter.