bloc_pattern 2.5.1

  • Readme
  • Changelog
  • Example
  • Installing
  • 98

Bloc Pattern #


Package that helps you implementing BloC Pattern by Dependency Injection in your project.

Package #


What is BloC? #

BLoC stands for Business Logic Components. The gist of BLoC is that everything in the app should be represented as stream of events: widgets submit events; other widgets will respond. BLoC sits in the middle, managing the conversation. It will be created separately from the view, isolating the logic of the code.

Why to use bloc_pattern? #

It's perfect to organize, and follow the best practices in your code, taking vantage of Dependency Injection. And it's the best package to use with slidy (created to structure your Flutter project).

How to implement? #

First step. #

Add bloc_pattern in your pubspec.yaml.


  bloc_pattern: ^2.3.2

Or you can use slidy to add in your dependencies:

slidy install bloc_pattern

Starting to code #

1. #

Create the BloC class of your module, and extends from BlocBase.

import 'package:bloc_pattern/bloc_pattern.dart';
import 'package:rxdart/rxdart.dart';

class CounterBloc extends BlocBase{

  Observable<int> counter; // observable (Stream)

  CounterBloc() {
    counter = Observable.merge([ //merges the both streams 
    ]).startWith(0) //starts with the value 0(the initial data)
    .scan((acc, curr, i) => acc + curr, 0 /* inital value: 0 */) // scans the old(acc) and the current(curr) value, and sum them
    .asBroadcastStream(); //turns the stream into a Broadcast straem(it can be listened to more than once)

  final _increment = new BehaviorSubject<int>(); //the BehaviorSubject gets the last value
  final _decrement = new BehaviorSubject<int>();

  void increment() => _increment.add(1); //method to increment
  void decrement() => _decrement.add(-1);//method to decrement

  void dispose() {// will be called automatically 


2. #

Now wrap your MaterialApp into a BlocProvider. Obs.: BlocProvider is the widget where you can Inject all the BloCs, and then recover them anywhere in your application.

class MyApp extends StatelessWidget {
  // This widget is the root of your application.
  Widget build(BuildContext context) {
    return BlocProvider(
        blocs: [
          Bloc((i) => CounterBloc()),
          child: MaterialApp(
        title: 'Flutter Demo',
        theme: ThemeData(
        home: MyHomePage(title: 'Flutter Demo Home Page'),

Recovering the BloC class. #

    //recovering your BloC
  final bloc = BlocProvider.getBloc<CounterBloc>();

Using StreamBuilder #

The StreamBuilder widgets lets you change the UI reactively without needing to call setState()(that rebuilds the stateful widget);

                stream: bloc.outCounter,  //here you call the flux of data(stream)
                builder: (BuildContext context, AsyncSnapshot snapshot) {
                  return Text(
                    style: Theme.of(context).textTheme.display1,

Consuming the BloC directly from the Widget #

You can consume your BloC directly from the target Widget using the Consumer() class. Everytime the CounterBloc adds a new value, the widgets within the Consumer will have new data. You can see the project source code here.

BloC using Consume(): #

class CounterBloc {
int counter = 0;
  notifyListeners(); //notifies when occurs a change


            builder: (BuildContext context, CounterBloc bloc) {
              return Text(bloc.counter.toString()); //calling the counter value
            height: 25.0,
            builder: (BuildContext context, CounterBloc bloc) {
              onPressed: () {
                bloc.onChanged(); //calling onChanged() that will increment the value
              child: Icon(Icons.add),

Dependency Injection #

You can also inject other dependencies aside BloC:

void main() => runApp(MyApp());

class MyApp extends StatelessWidget {
  // This widget is the root of your application.
  Widget build(BuildContext context) {
    return BlocProvider(
      child: MaterialApp(
        home: IncrementWidget(),
      //add yours BLoCs controlles
       blocs: [
        Bloc((i) => IncrementController(i.get<GeneralApi>({"name":"John"}))),
        Bloc((i) => DecrementController())
      //add Other Object to provider
      dependencies: [
        Dependency((i) => GeneralApi(i.params['name'])), //repository

You can define if the dependency will be a Singleton or not:

Bloc((i) => CounterBloc(), singleton: false)

To inject the dependency in your class use:

  Widget build(BuildContext context) {
    //recovering your API dependency
  final GeneralApi api = BlocProvider.getDependency<GeneralApi>(); //repository
  //Passing Data through parameters
  final UserModel user = BlocProvider.getDependency<UserModel>({
    "id": 1,
    "name": "João"

Tags #

You can create new BlocProviders independently.

  • Use the property "tagText" giving a name for your new BlocProvider.
  • When you have more than one BlocProvider, you will need to use its tag to indentificate, otherwise it should return an error.

  Widget build(BuildContext context) {
    return BlocProvider(
      //tag module
      tagText: "newModule",

Calling the dependencies and BloCs from other classes:


ModuleWidget #

The ModuleWidget uses Tag Module in its structure:

  • Implicity creates a tag for the module class.
  • Gets automatically the tag when you call the module BloC.

You can use Slidy to create the module

class HomeModule extends ModuleWidget {

  //Inject the blocs
  List<Bloc<BlocBase>> get blocs => [
        Bloc((i) => IncrementController())),
        Bloc((i) => DecrementController())

  //Inject the dependencies
  List<Dependency> get dependencies => [
        Dependency((i) => GeneralApi(i.params['name'])),

  //main widget
  Widget get view => HomeWidget();

  //shortcut to pick up dependency injections from this module
  static Inject get to => Inject<HomeModule>.of();


So instead of using BlocProvider and tags, you can just use ModuleWidget, it will also organize and modularize your project.

  //instead of

Dispose #

It's important to always call the dispose(), to make sure that the objects won't continue processing when you don't have any data.

The BlocBase already comes with Disposable, you just need to override it and will be called automatically in your ModuleWidget

class YourBloc extends BlocBase {

  void dispose(){
    //dispose Objects

To do this manually or restart some injected singleton, use:

//dispose BLoC

//dispose dependency

//dispose BLoC in Module

//dispose BLoC in ModuleWidget<BlocController>();

[Optional] Extends Disposable in your service or repository for automatic dispose.

class Repository extends Disposable {

  void dispose(){
    //dispose Objects

Tests #

You can start your modules in the test environment and use dependency injections directly.

import 'package:flutter_test/flutter_test.dart';

void main() {
  //start Module and Dependency Injection
  AppBloc bloc;

  setUp(() {
    //get bloc
    bloc =<AppBloc>();

  group('AppBloc Test', () {
    test("Counter Test", () {
      expect(bloc.counter, 1);
    test("Class Test", () {
      expect(bloc, isInstanceOf<AppBloc>());

You can also override injection elements in initModule. Use this to replace your client with a Mock.

import 'package:flutter_test/flutter_test.dart';

class MockClient extends Mock implements Dio {}

void main() {
  //start Module and Dependency Injection
  initModule(AppModule(), changeDependencies: [
      Dependency((i) => MockClient() as Dio),

You can create your mocks based on the "BlocProvider.isTest" static property, which returns a boolean.

For more information #

Access Flutterando Blog.

2.5.1 (Nov 14, 2019) #

  • Fix dispose module error

2.5.0 (Nov 08, 2019) #

  • Added generic support for any class bloc

2.4.4 (Nov 01, 2019) #

  • Added change inject in initModule (tests)

2.4.2+1 (Out 25, 2019) #

  • Added bloc_pattern_test from tests.

2.4.1+1 (Out 21, 2019) #

  • Fix Module Not Found error

2.4.0+2 (Out 06, 2019) #

  • Added distinct parameter in Consumer Widget and condition to call builder. Consumer
  • Added specific Consumer for Modules Pattern ConsumerModule<HomeModule, HomeBloc>(...);

2.3.4 (Out 03, 2019) #

  • Fix error singleton blocs module
  • Added debugMode false to print texts

2.3.3 (Sep 26, 2019) #

  • Fix error in segments bloc

2.3.2 (Sep 13, 2019) #

  • Fix multiple tags error

2.3.1 (Aug 24, 2019) #

  • Mapped Errors in Custom Exception

2.3.0 (Aug 23, 2019) #

  • Mapped Errors in Custom Exception

2.2.3 (Jul 11, 2019) #

  • Fix error dispose unique bloc

2.2.2+3 (Jun 28, 2019) #

  • Add ConsumerModule

2.2.1 (Jun 22, 2019) #

  • Prepare to Slidy
  • Fix error inject module.

2.2.0+5 (Jun 21, 2019) #

  • Fix error consumer module.

2.2.0+4 (Jun 19, 2019) #

  • Fix error dispose bloc.

2.2.0+1 (Jun 14, 2019) #

  • Introduced project modules.
  • Tag for each BlocProvider. You can use multiple BlocProvider independently.

2.1.9+2 #

  • Fix dispose error

2.1.9 #

  • Add Consumer pattern.

2.1.7 #

  • Corrections in the parameters.

2.0.1 (May 1, 2019) #

  • BlocProvider and BlocProviderList are now one.
  • Added Injection of BLoC dependencies.
  • Added Injection Dependencies.

1.1.2 (December 8, 2018) #

  • removed context injection

1.1.1 (December 8, 2018) #

  • removed context injection

1.1.0 (November 19, 2018) #

  • Injected the context (BuildContext) into the controller.

1.0.0 (November 19, 2018) #

  • Support for Dart 2.1
  • Enhanced Bloc lifecycle with fast access anywhere in the application.

0.1.0 (November 8, 2018) #

  • Provider with StatefulWidget.


import 'package:flutter/material.dart';
import 'package:exampleinjector/app/app_module.dart';

void main() => runApp(AppModule());

Use this package as a library

1. Depend on it

Add this to your package's pubspec.yaml file:

  bloc_pattern: ^2.5.1

2. Install it

You can install packages from the command line:

with Flutter:

$ flutter pub get

Alternatively, your editor might support flutter pub get. Check the docs for your editor to learn more.

3. Import it

Now in your Dart code, you can use:

import 'package:bloc_pattern/bloc_pattern.dart';
Describes how popular the package is relative to other packages. [more]
Code health derived from static analysis. [more]
Reflects how tidy and up-to-date the package is. [more]
Weighted score of the above. [more]
Learn more about scoring.

We analyzed this package on Mar 31, 2020, and provided a score, details, and suggestions below. Analysis was completed with status completed using:

  • Dart: 2.7.1
  • pana: 0.13.6
  • Flutter: 1.12.13+hotfix.8

Health suggestions

Format lib/bloc_pattern_test.dart.

Run flutter format to format lib/bloc_pattern_test.dart.

Format lib/src/bloc_provider_error.dart.

Run flutter format to format lib/src/bloc_provider_error.dart.


Package Constraint Resolved Available
Direct dependencies
Dart SDK >=2.0.0-dev.68.0 <3.0.0
flutter 0.0.0
Transitive dependencies
collection 1.14.11 1.14.12
meta 1.1.8
sky_engine 0.0.99
typed_data 1.1.6
vector_math 2.0.8
Dev dependencies
bloc ^2.0.0
flutter_bloc ^2.0.0
flutter_mobx ^0.3.3+1
mobx ^0.3.9+1
rxdart ^0.22.6