Quick Summary

This Flutter BLoC tutorial covers BLoC state management in your application. It explains how to use it and helps developers manage their application states efficiently. Moreover, the BloC pattern can help you control the data flow in your application and centralize the user interface.

Table of Contents

Introduction

Do you know you need to track changes in data and updated UIs in your Flutter application?

Yes, your app grows, and you need to keep track of changing data and updated UIs according to the app’s requirements. This is where state management comes into the picture, as it offers a proper structure approach to managing application state in Flutter.

In essence, state management helps control your application’s data flow and centralize the UI state with built-in mechanisms. This blog delves into Flutter BLoC, a popular state management technique that separates business logic from the UI. We’ll explore how BLoC simplifies your development process and fosters cleaner, more maintainable code.

What is BLoC?

BLoC stands for Business Logic Components. It aims to separate the application’s business logic from the User Interface, making the application code more unambiguous, scalable, and testable.

  • Developed by: Felix Angelov
  • Sponsors: Very Good Ventures, Stream, Miquido
  • Version: flutter_bloc: ^8.0.1
BLoC

Pros & Cons of BLoC Design Pattern

Before moving forward in the flutter bloc tutorial, let’s examine some of the pros and cons of the bloc design pattern.

Pros of Using BLoC

  • Excellent documentation about different scenarios.
  • It separates business logic from the UI, hence making the code easy to understand.
  • It makes the product more testable.
  • It is easy to keep track of states an app went through.

Cons of Using BLoC

  • The learning curve is a bit steep.
  • Not recommended for simple applications
  • More boilerplate code, but that can be taken care of by extensions.

Flutter BLoC Tutorial Goal

We will build a relatively simple application to demonstrate how the BLoC uses streams to manage states and write some tests for the bloc.

We will build a text change application; press text will be changed and displayed with each button. You can refer below GIF for the same.

Flutter BLoC Tutorial Goal

Initial Setup

1. Make sure to install the bloc extension in your editor; it will help create all boilerplate code and files required for the project(right-click on the lib folder, and it will give you the option for generation bloc Flutter for your project).

2. Make sure to match your pubspec.yaml file with mine to avoid any issues.

Folder Structure of Flutter BLoC Simple Example

Want to have easy, scalable, and hustle-free Flutter application development?
Bacancy is here for you! Contact us to hire Flutter developer who will efficiently fulfill your project requirements and have commendable problem-solving skills.

Understanding BLoC Concepts: Events and States

To understand how it works, we need to know what events and states with this Flutter BLoC tutorial.

  • Events: It is an application’s inputs (like button_press to load images, text inputs, or any other user input that our app may hope to receive).
  • States: It simply the application’s state, which can be changed in response to the event received.

Bloc manages these events and states, i.e., it takes a stream of Events and transforms them into a stream of States as output.

Understand Events and States

Creating an Event

Copy Text
@immutable
abstract class AppBlocEvent {
 const AppBlocEvent();
}
 
@immutable
class ChangeTextEvent extends AppBlocEvent {
 const ChangeTextEvent();}

Moving forward in the flutter bloc tutorial. Here we have created a ChangeTextEvent, which will be fired when a button is clicked.

We have an abstract AppBlocEvent class because Bloc expects a single event to be added to the stream. Still, as an app can have multiple events, we create an abstract class and extend it whenever we want to create a new event for handling and passing multiple events to the Flutter bloc example.

Creating a State

Copy Text
@immutable
class AppState extends Equatable {
 final int index;
 final String text;
 
 const AppState.empty()
     : index = 0,
       text = 'Initial Text';
 
 const AppState({
   required this.index,
   required this.text,
 });
 
 @override
 List<Object> get props => [index, text];
}

Similarly, we can create different states here in this app. We do not have many states. Therefore, we have created a single state to manage the app; however, we can create multiple states similar to events by creating an abstract appstate and extending it to our custom states.

  • AppState.emptyis simply the initial state in which the application loads initially.
  • Equatable (get props) here is used to compare to states. If they are equal, it will be used to test the bloc in Flutter.

Event and State Management using BLoC Pattern

Copy Text
class AppBlocBloc extends Bloc {
 final List textList = [
   'Initial Text',
   'Changed Text',
   'Changed Again',
 ];
 AppBlocBloc() : super(const AppState.empty()) {
   on((event, emit) {
     try {
       int newIndex = state.index + 1;
       if(newIndex >= textList.length) {
         newIndex = 0;
       }
       emit(
         AppState(
           index: newIndex,
           text: textList[newIndex],
         ),
       );
     } on Exception catch (e) {
       // ignore: avoid_print
       print(e);
     }
   });
 }
}

Explanation
This is the part that contains the business logic of our application.

  • on is executed when ChangeTextEvent is added to the stream via a button click , it receives the event, i.e., any information that you want to pass along with triggering event you can access it using this(like event.any_info – you have to change your event class accordingly), emit which is used to emit a state for that particular event.
  • state.index lets you access the current state of the application.
  • emit(AppState(…)): emit(…) is used to output new states and causes the rebuild of the build() function.

Put the pieces together.
Till now, events, states, bloc, and our application’s UI are not connected in any way. Let’s start piecing them together.

Providing our BLoC

Copy Text
import 'package:flutter/material.dart';
import 'package:flutter_bloc/flutter_bloc.dart';
import 'package:text_change/text_controller.dart';

import 'bloc/app_bloc_bloc.dart';
import 'bloc/app_bloc_state.dart';

class App extends StatelessWidget {
  const App({Key? key}) : super(key: key);

  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      title: 'Flutter Demo',
      theme: ThemeData(
        primarySwatch: Colors.blue,
      ),
      home: BlocProvider(
        create: (context) => AppBlocBloc(),
        child: Scaffold(
          appBar: AppBar(
            title: const Text('Text Change'),
          ),
          body: BlocConsumer(
            listener: (context, state) {},
            builder: (context, state) {
              return TextController(
                text: state.text,
              );
            },
          ),
        ),
      ),
    );
  }
}

Explanation: App.dart
BlocProvider(…): we use it to provide an instance of our bloc by placing it just below the root of the application so that it is accessible throughout it.

  • create: it creates the instance of our AppBloBloc.

BlocConsumer(…): It is the area where everything happens.

  • It has a property called listener, which listens for state changes and can react in a particular way to a specific state along with state change.
  • builder: it is responsible for building the UI and is rebuilt for each state change. blocConsumer also contains listenWhen and buildWhen, which as the name states, can be tailored to react to specified states.

Triggering the Event and States

Copy Text
class TextChangeController extends StatelessWidget {
final String text;

const TextChangeController({Key? key, required this.text}) : super(key: key);

@override 
Widget build (BuildContext context) { 
      return Column
         children:  [ 
            TextChange(
               text: text, 
            ), // TextChange 
           ElevatedButton( 
               onPressed: () =>
                    context.read().add(const ChangeTextEvent()), 
              child: const Text('Change Text'), 
         ), // ElevatedButton 
      ), // [ ] 
   ); // Column
  )
)

Here we have added ChangetTextEvent onto the event stream, thereby triggering state change which causes the rebuild of the builder() in BlocConsumer, and changed text is displayed up on the screen.

There you have it!! With separated UI and business logic, you can change the UI code and just plug the Bloc in. It will work the same.

Are you willing to build a demo application and learn to work with freezed in your flutter app?

Flutter Freezed Example

Testing the BLoC Design Pattern

For testing the bloc, you require two packages:

  • bloc_test
  • flutter_test

Simply inside the test folder, create the app_bloc_test.dart file and start writing test.
Inside we are going to test two conditions:

  • Initial state of application i.e AppState.empty().
  • State changes when the button is pressed.

There you go!!??

Copy Text
void main() {
 blocTest(
   'Initial State',
   build: () => AppBlocBloc(),
   verify: (appState) =>
       expect(appState.state, const AppState.empty(), reason: 'Initial State'),
 );
 blocTest(
   'emits [MyState] when MyEvent is added.',
   build: () => AppBlocBloc(),
   act: (bloc) => bloc.add(const ChangeTextEvent()),
   expect: () => const [
     AppState(
       index: 1,
       text: 'Changed Text',
     ),
   ],
 );
}

Explanation

  • blocTest is coming from the bloc_test package.
  • build(): it returns an instance of AppBlocBloc().
  • verify and expect as the name suggests they match the state expect(actual, matcher, reason).
  • act: Add an event to the event stream.

Github Repository: Flutter BLoC Simple Example

Feel free to clone the repository: flutter-bloc-demo and start experimenting with the code.

Conclusion

The Flutter BLoC tutorial was helpful for you to get started with state management using the BLoC pattern. We will be back with another Flutter tutorial; till then, visit the Flutter tutorials page and learn more about Flutter concepts. Let us know if you want any specific topics to be covered. Write us back your suggestions and feedback. Happy Coding!

Frequently Asked Questions (FAQs)

Following are the advantages of utilizing BLoC in the Flutter project is-

  • Keep UI code clean
  • Manage to centralize
  • Enhance testability
  • Write code for business logic

Here are some real-world examples of Flutter BloC in applications:

  • eCommerce application through user authentication
  • Complex form with validation logic
  • Chat application

Simplify Your Development Process With Flutter BLoC

Empower your application with our Flutter professional’s expertise to accelerate your development and benefit your project.

BOOK A 30 MIN CALL

Build Your Agile Team

Hire Skilled Developer From Us

[email protected]

Your Success Is Guaranteed !

We accelerate the release of digital product and guaranteed their success

We Use Slack, Jira & GitHub for Accurate Deployment and Effective Communication.

How Can We Help You?