Why do we use BloC Pattern ?
It is a Design Pattern and It stands for Business Logic Component. So we can use the Bloc Pattern whenever we need to manage the state of the UI and have to update it automatically when data changes.
You may also check our Flutter app development company page
There should be a bloc in between the data layer and UI because this Bloc creates a connection between the data layer and UI which consequently manages the state of the UI accordingly.
Below all three images will change when we, clicking on the Change Image button as the input event changes.
How to use this pattern
Let’s create a program that will change the UI image as we click on the Change Image button.
Bloc does the process of mapping events to the state.
In this project, we initially provide the 0 value as input to the event to show a default image on the screen.
On pressing the Change Image button, we calculate the value which is increased by one in the block, and use check on button press and then send event according to the condition.
We need to create three files in our project:
1 . Main. dart
2 . HomeScreen
3 . ChangeImage
Now first of all add the package to pubspec.yaml file
1 2 |
bloc: ^7.0.0 flutter_bloc: ^7.0.1 |
Let’s Check Implementation in Main.dart
From the root of the application, we provide the initial value to the change image class. And make Ui class as a child of BlocProvider
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 |
import 'package:flutter/material.dart'; import 'package:flutter_bloc/flutter_bloc.dart'; import 'bloc_file.dart'; import 'homescreen.dart'; void main() { runApp(MyApp()); } class MyApp extends StatelessWidget { // This widget is the root of your application. @override Widget build(BuildContext context) { return MaterialApp( debugShowCheckedModeBanner: false, // Wrapping UI class with BlocProvider home: BlocProvider( // Initial input create: (_)=> ChangeImage(0), child: HomeScreen()), ); } } |
Now Check Implementation in HomeScreen
In the below code, we are doing the UI part in which we are providing the automatically updated input on the button click which eventually results in updating the UI automatically.
And BlocBuilder is used to show changes that will counter from bloc file along with this it also manages state as events changed.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 |
import 'package:flutter/cupertino.dart'; import 'package:flutter/material.dart'; import 'package:flutter_bloc/flutter_bloc.dart'; import 'bloc_file.dart'; class HomeScreen extends StatefulWidget { @override _HomeScreenState createState() => _HomeScreenState(); } class _HomeScreenState extends State<HomeScreen> { int num = 1; @override Widget build(BuildContext context) { final _imageVar = BlocProvider.of<ChangeImage>(context); return Scaffold( appBar: AppBar( title: Text("BLoC State Management"), ), body: SingleChildScrollView( child: Center( child: Column( mainAxisAlignment: MainAxisAlignment.center, crossAxisAlignment: CrossAxisAlignment.center, children: [ SizedBox( height: 20.0, ), //Wrap with BlocBuilder where we want to show update in UI BlocBuilder<ChangeImage, int>( builder: (BuildContext context, int state) { if (state % 3 == 1) { return Icon( Icons.add_shopping_cart, size: 180.0, color: Colors.green, ); } else if (state % 3 == 2) { return Icon( Icons.build, size: 180.0, color: Colors.red, ); } else if (state % 3 == 0) { return Icon( Icons.add_call, size: 180.0, color: Colors.blue, ); } else { return Container(); } }), SizedBox( height: 80, ), Container( padding: EdgeInsets.all(6.0), width: MediaQuery.of(context).size.width, child: ElevatedButton( onPressed: () { if (num % 3 == 1) { _imageVar.add(ImageUpdater.zero); } else if (num % 3 == 2) { _imageVar.add(ImageUpdater.one); } else if (num % 3 == 0) { _imageVar.add(ImageUpdater.two); } setState(() { num = num + 1; }); }, child: Text("Change Image")), ), Row( mainAxisAlignment: MainAxisAlignment.center, children: [ Text("Note -",style: TextStyle(fontWeight: FontWeight.bold),), Text(" You can change state of image by pressing button"), ], ) ], ), ), ), ); } } |
Let’s Check Implementation in ChangeImage
And this is the bloc part of the project where events are taken as input and update the state accordingly and we will be using the switch to check events from the input.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 |
import 'dart:async'; import 'package:bloc/bloc.dart'; enum ImageUpdater {zero,one,two,} class ChangeImage extends Bloc<ImageUpdater, int>{ ChangeImage(int initialState) : super(initialState); @override //managing state according to input event Stream<int> mapEventToState(ImageUpdater event)async* { switch(event){ case ImageUpdater.zero: yield state+1; break; case ImageUpdater.one: yield state +1; break; case ImageUpdater.two: yield state +1; break; } } } |
I hope this blog will help you to learn about Bloc Pattern and you will be able to implement it.
Happy Learning ✍️
Reference Links:
https://pub.dev/packages/flutter_bloc