In this article we are going to show you how to quickly - and somehow dirtily - introduce bloc to your flutter application.

Let’s start with standard counter application in flutter.

Before we begin, we need to introducing bloc library. To do this we add the dependency to our pubspec.yaml file

  flutter_bloc: {latest_version}

After that you run pub get as usual, and congrats! You have bloc in your application.

Step 1: Create a state class with all your state variables.

Next step is to create a simple DTO (Data Transfer Object) with your state data. Your state is usually the data variables in your State class. Remember that if your widget is stateless, you probably don’t need Bloc to start with. In this example we have one such variable:

  int _counter = 0;

It is the value of the counter we show to the user. So our DTO, or more precisely state class is going to be

class State {
  final int counter;
}

Now, there are some things to remember here. Bloc re-renders your widgets if the state class changes. In order to understand this, state class should be implemented in a way that if any of its properties changes, it reflects in its equality. There are different ways of doing this, but they are subjects for different posts. For now we are going to simply implement it ourselves.

class CounterState {
  int counter;

  State(this.counter);

  @override
  bool operator ==(Object other) {
    if (other is State && other.counter == counter) {
      return true;
    }
    return false;
  }
}

Step 3: write your Bloc class with all the operations

Now, we need our bloc class. A Bloc class is a class that extends Bloc or Cubit. Cubit is much more simpler to understand and reason about so we are doing that

class CounterCubit extends Cubit<CounterState>

As you see, we give our state class to the Cubit as a type argument.

Now we need to satisfy its constructor:

class CounterCubit extends Cubit<CounterState> {
  CounterCubit(CounterState st) : super(st);
}

Now that we have our class, we should move all our business logic methods to this class.

If you skim the code, the only business logic we have is increasing the value of the counter. So we need a method to do that. The most important point is that, this process should create a new state, this way the framework understands that state changed, and it should recreate the related widgets.

var newState = CounterState(state.counter + 1);

Beside this, there is a trick to Bloc. Anytime you change your state, you have to emit it; this is the bloc way of saying, hey, something might have changed, pay attention

var newState = CounterState(state.counter + 1);
emit(newState);

Step 3: Use a Bloc widget

Now that we have our state and our Bloc, it is time to use them in the build method of our class. There are many ways to do that. We are going to do the simplest one: BlocProvider

One thing to note is that because the BlocProvider class is a stateful widget, we don’t need our class to be stateful

We are going to change the MyApp widget to have a BlocProvider

 Widget build(BuildContext context) {
    return MaterialApp(
      title: 'Flutter Demo',
      theme: ThemeData(
        colorScheme: ColorScheme.fromSeed(seedColor: Colors.deepPurple),
        useMaterial3: true,
      ),
      home: BlocProvider(
        create: (context) => CounterCubit(CounterState(0)),
        child: const MyHomePage(title: 'Flutter Demo Home Page'),
      ),
    );
  }

Then we change the MyHomePage widget to use the bloc:


class MyHomePage extends StatelessWidget {
  const MyHomePage({super.key, required this.title});
  final String title;

  @override
  Widget build(BuildContext context) {
    return BlocBuilder<CounterCubit, CounterState>(
        builder: (BuildContext context, CounterState state) {
      return Scaffold(
        appBar: AppBar(
          backgroundColor: Theme.of(context).colorScheme.inversePrimary,
          title: Text(title),
        ),
        body: Center(
          child: Column(
            mainAxisAlignment: MainAxisAlignment.center,
            children: <Widget>[
              const Text(
                'You have pushed the button this many times:',
              ),
              Text(
                '${state.counter}',
                style: Theme.of(context).textTheme.headlineMedium,
              ),
            ],
          ),
        ),
        floatingActionButton: FloatingActionButton(
          onPressed: context.read<CounterCubit>().increase,
          tooltip: 'Increment',
          child: const Icon(Icons.add),
        ),
      );
    });
  }
}

Things to note is that

  • We use state.counter instead of couter state.
  • We use the method on Bloc to increment the counter. context.read<CounterCubit>().increase

And this is the final product:

That is it folks. Have fun Blocing!