Skip to content

md-siam/bloc_tutorial

Repository files navigation

           

BLoC Tutorial

In the Flutter Bloc Essential course, you can learn in depth about Bloc, the popular Flutter state management solutions.

In particular, it covers only the most recent version, version 8.0 or higher.

If you want to deepen your understanding of the Flutter Bloc and put all the concepts into practice, then this course is for you.

The lecture was carefully composed to ensure a balance between theory and practice.

And under the belief that repetition is the most important learning method, whenever there is a new concept, we will test the concept by making a small app, and through real-world apps such as TODO, Weather, and Firebase Authentication app, the concepts will come together comprehensively.

BLoC Overview

Few common widgets from the flutter_bloc package:

1. BlocBuilder

BlocBuilder<BlocA, BlocAState>(
    bloc: blocA,  // provide the local bloc instance
    buildWhen: (previousState, state){
        // return true/false to determine whether or not
        // to rebuild the widget with state
    },
    builder:(context, state){
        // return widget here based on BlocA's state
    }
)

2. BlocListener

BlocListener<BlocA, BlocAState>(
    bloc: blocA,  // provide the local bloc instance
    listenWhen: (previousState, state){
        // return true/false to determine whether or not
        // to call listener with state
    },
    listener:(context, state){
        // do stuff here based on BlocA's state
    },
    child: Container(),
)

3. BlocConsumer

It is the combination of BlocBuilder & BlocListener

BlocConsumer<BlocA, BlocAState>(
    bloc: blocA,  // provide the local bloc instance
    listenWhen: (previousState, current){
        // return true/false to determine whether or not
        // to call listener with state
    },
    listener:(context, state){
        // do stuff here based on BlocA's state
    },
    buildWhen: (previousState, current){
        // return true/false to determine whether or not
        // to rebuild the widget with state
    },
    builder:(BuildContext context, BlocAState state){
        // return widget here based on BlocA's state
    }
)

4. Extension methods on BuildContext

When we needed to use multiple states at the same time, then we should use these extensions for code readability.

    ◉ context.watch<T>(), which makes the widget listen to change on T
    ◉ context.read<T>(), which returns T without listening to it
    ◉ context.select<T, R>(R cb(T value)), which allows a widget to listen
      to only a small part of T.
    BlocProvider.of<T>(context) = context.read<T>()
    BlocProvider.of<T>(context, listen: true) = context.watch<T>()

5. Process of creating a STATE

 Step-by-step process for creating a cubit/bloc:
    1. create ClassState
    2. create variable
    3. Generate `Constructor`
    4. ClassState `extends` Equatable
    5. Generate `Equitable`
    6. Generate `toString()`
    7. Generate `copyWith()`
    8. write `factory` contactor (i.e. CounterState.initial())

6. Cubit_2_Cubit & Bloc_2_Bloc Communication

Cubit to Cubit & Bloc to Bloc communication can be developed using:

    ◉ cubit + StreamSubscription
    ◉ cubit + BlocListener
    ◉ bloc + StreamSubscription
    ◉ bloc + BlocListener

7. Routing using Bloc

    1. Anonymous Route Access
    2. Named Route Access
    3. Generated Route Access

8. Observing CubitBlocs

9. Bloc Observer Template

import 'package:bloc/bloc.dart';

class CounterBlocObserver extends BlocObserver {
  @override
  void onEvent(Bloc bloc, Object? event) {
    super.onEvent(bloc, event);
    print('ColorBlocObserver(event): ${bloc.runtimeType}, $event');
  }

  @override
  void onError(BlocBase bloc, Object error, StackTrace stackTrace) {
    print('ColorBlocObserver(error): ${bloc.runtimeType}, $error, $stackTrace');
    super.onError(bloc, error, stackTrace);
  }

  @override
  void onChange(BlocBase bloc, Change change) {
    super.onChange(bloc, change);
    print('ColorBlocObserver(change): ${bloc.runtimeType}, $change');
  }

  @override
  void onTransition(Bloc bloc, Transition transition) {
    super.onTransition(bloc, transition);
    print('ColorBlocObserver(transition): ${bloc.runtimeType}, $transition');
  }
}

How to implement it in the main function?

void main() {
  /// this [Bloc.observer] is only of `debugging` purpose
  ///
  Bloc.observer = ColorBlocObserver();

  runApp(const MyApp());
}

10. Event Transformation

Bloc 7.2.0 and Bloc 8.0.0 introduce a new way to register event handlers. With this change comes several benefits, including reduced boilerplate, better consistency with cubit, and, most of all, concurrent event processing — by default!

Note: Read the detailed documentation of Event Transformation

dependencies:
  equatable: ^2.0.5
  # For state management
  bloc: ^8.1.0
  flutter_bloc: ^8.1.1

  # For Event Transform
  bloc_concurrency: ^0.2.0

11. Hydrated Bloc

12. Repository Provider

13. Cubit vs. Bloc

14. States

  • Independent States
  • Computed States
    • StreamSubscription
    • BlocListener

15. Best Practice

  • Make the state as atomic as possible

    • If it can logically separated, create a separate state and manage it
  • State is mainly managed in the form of a class

    • Group and manage logically related values
    • Classify and manage primitive type variables such as String and int - The advantage of avoiding type conflicts
  • Immutable state

    • Create a new state using the copyWith function
  • Always extends Equatable class

    • Ease of equality check of object instances
    • Provides convenience functions such as stringify

App Screenshots

1. Bloc Overview:

Folder No. Name of the App Logic Files Screenshots
1 Counter Using Cubit counter_cubit.dart
counter_state.dart
2 Counter Using Bloc counter_bloc.dart
counter_event.dart
counter_state.dart
3 Bloc Payload theme_bloc.dart
theme_event.dart
theme_state.dart
4 Cubit Payload theme_cubit.dart
theme_state.dart
5 Cubit 2 Cubit color_cubit.dart
color_state.dart
counter_cubit.dart
counter_state.dart
6 Cubit 2 Cubit Listener color_cubit.dart
color_state.dart
counter_cubit.dart
counter_state.dart
7 Bloc 2 Bloc color_bloc.dart
color_event.dart
color_state.dart
counter_bloc.dart
counter_event.dart
counter_state.dart
8 Bloc 2 Bloc Listener color_bloc.dart
color_event.dart
color_state.dart
counter_bloc.dart
counter_event.dart
counter_state.dart
9 Bloc Context counter_cubit.dart
counter_state.dart
10 Bloc Anonymous counter_cubit.dart
counter_state.dart
11 Bloc Named counter_cubit.dart
counter_state.dart
12 Bloc Generated counter_cubit.dart
counter_state.dart
13 Bloc 2 Bloc color_bloc_observer.dart
counter_bloc_observer.dart
14 Event Transform counter_bloc.dart
counter_event.dart
counter_state.dart
15 Hydrated Bloc counter_bloc.dart
counter_event.dart
counter_state.dart

2. TODO App:

About

Few application developers using bloc state management solution

Resources

Stars

Watchers

Forks

Releases

No releases published

Packages

No packages published