DEV Community

AbhishekDoshi26
AbhishekDoshi26

Posted on

Bloc Pattern in Flutter | Part 1💙

Bloc Pattern in Flutter | Part 1💙

Do you feel Bloc is tough? Me too!

Let’s make it easy then!😍

In this article, we will check out how to use Bloc in Flutter using flutter_bloc package with an example.

Package Link: flutter_bloc | Flutter Package (pub.dev)

So Bloc basically uses the concept of Inherited Widget. We can implement Bloc using Stream and Sink but, we already have a package **flutter_bloc **which is a wrapper of Stream and Sink.

Before we start bloc, there are two concepts that needs to be clear:

  • Events: Events are basically the functionalities of the app. Let’s say for our basic Counter app, Increment is a functionality and hence, one of our event is Increment.

  • States: *State is the information that can be read synchronously when the widget is built and might change during the lifetime of the widget. Or, in simple words, we can say that the State is something that our app is, before and after the event. **Hence, in our Counter example, the app before increment and after increment is State. Also, we can say that we have a state while it’s incrementing.*

In BLOC, we give Event **as **input **to BLOC. Then we do the **processing/business logic in the Bloc and provide State **as **output.

In a Bloc, there will be 3 main files:

  • bloc file: This file contains the main Business Logic

  • events file: This file states all the events that are present in your app.

  • state file: This file contains all the states that your app undergoes.

Let’s start with the coding!

We will re-write the basic Counter App using BLOC!

Step 1: Import flutter_bloc in pubspec.yaml

flutter_bloc: ^6.1.1
Enter fullscreen mode Exit fullscreen mode

Step 2: Create a folder named bloc and create 2 files in it. Here, we will name them as counter_bloc andcounter_event . As we don’t have multiple states, we won’t create counter_state .

This is how the project structure will look like. You can name your files according to your comfort.

Step 3: **Let’s first create the basic UI and functionality of our app by scratch without Bloc. Here’s the main.dart and home.dart files:
**main.dart:

import 'package:bloc_counter_example/home.dart';
import 'package:flutter/material.dart';

void main() {
  runApp(MyApp());
}

class MyApp extends StatelessWidget {
  [@override](http://twitter.com/override)
  Widget build(BuildContext context) {
    return MaterialApp(
      home: MyHomePage(),
    );
  }
}
Enter fullscreen mode Exit fullscreen mode

home.dart

import 'package:flutter/material.dart';

class MyHomePage extends StatefulWidget {
  [@override](http://twitter.com/override)
  _MyHomePageState createState() => _MyHomePageState();
}

class _MyHomePageState extends State<MyHomePage> {
  int counter = 0;

[@override](http://twitter.com/override)
  Widget build(BuildContext context) {
    return Scaffold(
      floatingActionButton: FloatingActionButton(
        child: Icon(Icons.add),
        onPressed: () => setState(() {
          counter++;
        }),
      ),
      appBar: AppBar(
        title: Text('Bloc Counter Example'),
      ),
      body: Center(
        child: Text(
          '$counter',
          style: TextStyle(fontSize: 50.0),
        ),
      ),
    );
  }
}
Enter fullscreen mode Exit fullscreen mode

So this is the basic application (Counter Application) that we created from scratch. Now, let’s work on our BLOC.

**Step 4: **Let’s create our events. As this is a simple example, we just have 1 event i.e. **Increment **and we don’t even need to pass any parameters. So we will use enum in this case. So, our counter_event.dart will look like this:

enum CounterEvent { increment }
Enter fullscreen mode Exit fullscreen mode

Step 5: Now, let’s work on our bloc file i.e. counter_bloc.dart .
In this file, we need to specify our business logic. We have to create a class that extends Bloc class. Let me show you how it will look:

import 'dart:async';
import 'package:bloc/bloc.dart';
import 'counter_event.dart';

class CounterBloc extends Bloc<CounterEvent, int> {
  CounterBloc() : super(0);

[@override](http://twitter.com/override)
  Stream<int> mapEventToState(CounterEvent event) async* {
    switch (event) {
      case CounterEvent.increment:
        yield state + 1;
        break;
      default:
        break;
    }
  }
}
Enter fullscreen mode Exit fullscreen mode

So, the above code is our counter_bloc.dart . This is the main core of our application that will increment the counter. Let’s break this code and understand:

  • class CounterBloc extends Bloc
    Here, **CounterEvent **is our event i.e. enum that we created in counter_event.dart and **int **is the state because we are simply incrementing an integer variable. If your application is complex, instead of int, you can specify your State class.

  • **CounterBloc() : super(0);
    **So, this is basically the constructor of CounterBloc() class where we pass an initial value i.e. 0 in our case to the parent class i.e. Bloc class because our CounterBloc extends Bloc.

  • Then we need to implement one method named mapEventToState . This method basically maps our input events with the corresponding output states.
    *Stream mapEventToState(CounterEvent event) async
    *This method takes Event as input and returns a Stream of state and hence we need to make it async. Now, if you have custom state file, you have to replace **int **with your state class.

  • Now, we check for the events. If it’s CounterEvent.increment, we need to increment the value. yield adds a value to the output stream of the surrounding async* function. It's like return, but doesn't terminate the function.

    switch (event) {
    case CounterEvent.increment:
    yield state + 1;
    break;
    default:
    break;
    }

Here, we complete our counter_bloc.dart file implementation!

So, our BLOC is ready! Now we just need to integrate it with our UI i.e. main.dart and home.dart files

I hope it was pretty clear till here! Don’t bang your laptop, we are just a few lines of code away 😉

**Step 6: **Open main.dart file and wrap the child of MaterialApp with BlocProvider. Your file will look like this:

import 'package:bloc_counter_example/bloc/counter_bloc.dart';
import 'package:bloc_counter_example/home.dart';
import 'package:flutter/material.dart';
import 'package:flutter_bloc/flutter_bloc.dart';

void main() {
  runApp(MyApp());
}

class MyApp extends StatelessWidget {
  [@override](http://twitter.com/override)
  Widget build(BuildContext context) {
    return MaterialApp(
      home: BlocProvider<CounterBloc>(
        create: (context) => CounterBloc(),
        child: MyHomePage(),
      ),
    );
  }
}
Enter fullscreen mode Exit fullscreen mode

So, basically BlocProvider will provide the access to Bloc throughout the Widget Tree.

BlocProvider<CounterBloc>(
        create: (context) => CounterBloc(),
        child: MyHomePage(),
      ),
Enter fullscreen mode Exit fullscreen mode

Here, CounterBloc is our bloc class that we created in previous step. We need to provide which bloc is to be created (here CounterBloc()) and the child where the bloc should be accessible. Yep! That’s it for main.dart file. Let’s now move to home.dart 😍

Step 7: **Open home.dart file and create an instance of **CounterBloc()

CounterBloc _counterBloc;
Enter fullscreen mode Exit fullscreen mode

Now, inside our build method, let’s instantiate our _counterBloc variable.

_counterBloc = BlocProvider.of<CounterBloc>(context);
Enter fullscreen mode Exit fullscreen mode

What does the above statement does??? It actually gives you access to the CounterBloc that we created. Now, using _counterBloc we can access our event and state.

Step 8: **Now, wrap the Text() widget (where we display the count) with **BlocBuilder

body: Center(
        child: BlocBuilder<CounterBloc, int>(
          builder: (context, state) {
            return Text(
              '$state',
              style: TextStyle(fontSize: 50.0),
            );
          },
        ),
      ),
Enter fullscreen mode Exit fullscreen mode

Here, the state variable that we can see, has access to the states. In this case, state is just an integer value which will get incremented. So we can directly display the state. Now, let’s change our Floating Action Button onPressed() method!

**Step 9: **In onPressed for Floating Action Button, we need to add the event to the bloc. Syntax:

onPressed: () => _counterBloc.add(CounterEvent.increment),
Enter fullscreen mode Exit fullscreen mode

This is how your home.dart file will look now:

import 'package:bloc_counter_example/bloc/counter_bloc.dart';
import 'package:flutter/material.dart';
import 'package:flutter_bloc/flutter_bloc.dart';
import 'bloc/counter_event.dart';

class MyHomePage extends StatefulWidget {
  [@override](http://twitter.com/override)
  _MyHomePageState createState() => _MyHomePageState();
}

class _MyHomePageState extends State<MyHomePage> {
  CounterBloc _counterBloc;

[@override](http://twitter.com/override)
  void dispose() {
    _counterBloc.close();
    super.dispose();
  }

[@override](http://twitter.com/override)
  Widget build(BuildContext context) {
    _counterBloc = BlocProvider.of<CounterBloc>(context);
    return Scaffold(
      floatingActionButton: FloatingActionButton(
        child: Icon(Icons.add),
        onPressed: () => _counterBloc.add(CounterEvent.increment),
      ),
      appBar: AppBar(
        title: Text('Bloc Counter Example'),
      ),
      body: Center(
        child: BlocBuilder<CounterBloc, int>(
          builder: (context, state) {
            return Text(
              '$state',
              style: TextStyle(fontSize: 50.0),
            );
          },
        ),
      ),
    );
  }
}
Enter fullscreen mode Exit fullscreen mode

And done!!!!!!!!!!!!!

We just implemented Bloc in our basic Counter Application💙

In the next article, we will take a complex application with multiple states and implement it using Bloc.

Hope you enjoyed this article!

GitHub Repository: AbhishekDoshi26/bloc_counter_example (github.com)

If you loved it, you can **Buy Me A Coffee!**

Don’t forget to connect with me on:

Top comments (4)

Collapse
 
machineno15 profile image
Tanvir Shaikh

Thank you for this, it's really helpful as I'm staring to learn flutter & very few resources to usderstand bloc.

Collapse
 
abhishekdoshi26 profile image
AbhishekDoshi26

Hope that it helps! You can support me by buying a coffee. Even small contribution counts😇

Collapse
 
bendelonlee profile image
Ben Lee

Somehow twitter links were added because you used the @ symbol in override. Annoying, is that built into DEV?

Collapse
 
bendelonlee profile image
Ben Lee

Thank you! First counter example of Flutter I found that wasn't deprecated