How to Use the BLoC Design Pattern for State Management in Flutter

In this tutorial, you can learn how to use the BLoC design pattern for state management in Flutter and how to implement any feature in BLoC.

Originally published by Pinkesh Darji at https://blog.logrocket.com/

When working on a Flutter app, you might encounter the need to split a large UI component into several smaller ones to improve the readability of the code. With multiple components, it’s crucial to implement effective communication between them. All UI components should be aware of the state of the app at all times. This is called state management.

In Flutter, you can manage the state of your app just by using setState. But while setState can be your best friend, it’s not a good idea to depend on it solely. There are many other factors you should also consider while developing a Flutter app, such as architecture, scalability, readability, complexity, etc. Staying on top of everything requires an effective state management technique.

There are myriad state management solutions available for Flutter, including Provider, InheritedWidget and InheritedModel, Redux, BLoC, GetIt, MobX, Riverpod, etc. In this tutorial, we’ll focus on using the BLoC design pattern for state management in Flutter. We’ll explain what BLoC means and demonstrate how to implement any feature in BLoC.

What is BLoC?

Business logic components (BLoC) allow you to separate the business logic from the UI. Writing code in BLoC makes it easier to write and reuse tests.

In simple terms, BLoC accepts a stream of events, processes the data based on events, and produces the output as states. Take the simple example below:

Process Events and Produces States

As soon as the Rotate 90° button is clicked, the RotateEvent is dispatched to BLoC and the state representing the rotation, i.e. RotatedState, is emitted. The triangle widget rotates itself upon receiving the RotatedState from the BLoC. Similarly, the circle widget changes its color when the Change color to Red button is clicked.

Since the BLoC handles the rotation and changing color operation, both operations can be performed on any widget. This facilitates the reusability of the code.

Important BLoC concepts

Before we dive in, let’s review some basic BLoC concepts and terms so we’re all on the same page.

Events

Events tell BLoC to do something. An event can be fired from anywhere, such as from a UI widget. External events, such as changes in network connectivity, changes in sensor readings, etc., look like this:

class RotateEvent {
  final double angle;

  const RotateEvent(this.angle);

  @override
  List<Object> get props => [angle];
}

BLoC

BLoC is a man in the middle. All the business logic sits inside the BLoC file. It simply accepts events, performs the logic, and outputs the states. Here’s how it looks:

class TransformationBloc
    extends Bloc<TransformationEvent, TransformationState> {
  TransformationBloc() : super(RotatedState(angle: 0);

  @override
  Stream<TransformationState> mapEventToState(
      TransformationEvent event) async* {
    if (event is RotateEvent) {
      yield RotatedState(angle: event.angle);
    }
  }
}

States

States represent the information to be processed by any widget. A widget changes itself based on the state.

class RotatedState {
  final double angle;

  const RotatedState({@required this.angle});

  @override
  List<Object> get props => [angle];
}

Cubit

Cubit is a simpler version of the BLoC pattern. It eliminates the need to write events.

Cubit exposes direct functions, which can result in appropriate states. Writing a Cubit instead of BLoC also reduces boilerplate code, making the code easier to read.

Here’s a simple example:

class TransformCubit extends Cubit<TransformState> {
  TransformCubit() : super(RotatedState(angle: 0));

  void rotate(double angle) {
    emit(RotatedState(angle: angle));
  }

}

Managing state in Flutter with setState (no BLoC)

Before we highlight the benefits of managing state in Flutter with BLoC, let’s walk through the process of using setState for state management instead.

Our example Flutter app will show a list of available products. A product can be added or removed from the cart by clicking the icon beside the product name. The number of items in the cart is updated accordingly:

Cart Updating

With setState, the entire UI is broken down into three classes:

  1. home.dart is the main file holding the scaffold and AppBar. AppBar contains the cart icon widget
  2. product_list.dart shows the list of products
  3. product_tile.dart shows the individual product item.

Here’s how it looks:

UI Broken Into Three Classes

The list of items in the cart is passed all the way from the Home (top) to the ProductTile (bottom) widget to check whether a given item exits in the cart or not. If it does, the cart icon will be highlighted.

Cart Icon Highlighted

Clicking on the cart icon beside the product name adds the item to the cart. The callback to refresh the cart icon on the AppBar is made from ProductTile (bottom) to Home (top).

Callback to Refresh Cart

**The problem with **setState

The setState approach to state management in Flutter works well for simple apps with just a few components. But for more complex, real-world Flutter apps with deep widget trees, using setState can lead to the following issues:

  • Code duplication — data has to be passed from all widgets to the bottom widget, which makes the code difficult to read
  • Performance degradation due to unnecessary redraws that result from lifting a setState to a parent widget with a deep hierarchy

How to manage state in Flutter with BLoC

Now let’s implement the same feature with BLoC.

First, add the BLoC library:

dependencies:
  flutter:
    sdk: flutter
  cupertino_icons: ^1.0.2
  flutter_bloc: ^7.0.0

Next, create and add a BLoC observer. This helps you determine the sequence of events and states that have occurred, which is great for debugging the app.

void main() {
  Bloc.observer = SimpleBlocObserver();
  runApp(MyApp());
}
import 'package:flutter_bloc/flutter_bloc.dart';

/// Custom [BlocObserver] which observes all bloc and cubit instances.
class SimpleBlocObserver extends BlocObserver {
  @override
  void onEvent(Bloc bloc, Object event) {
    super.onEvent(bloc, event);
    print(event);
  }

  @override
  void onTransition(Bloc bloc, Transition transition) {
    super.onTransition(bloc, transition);
    print(transition);
  }

  @override
  void onError(BlocBase bloc, Object error, StackTrace stackTrace) {
    print(error);
    super.onError(bloc, error, stackTrace);
  }
}

Create events to add and remove products from the list of cart items:

import 'package:equatable/equatable.dart';

abstract class CartEvent extends Equatable {
  const CartEvent();

  @override
  List<Object> get props => [];
}

class AddProduct extends CartEvent {
  final int productIndex;
  const AddProduct(this.productIndex);
  @override
  List<Object> get props => [productIndex];
  @override
  String toString() => 'AddProduct { index: $productIndex }';
}

Now, create states to represent a product being added and removed:

import 'package:flutter/material.dart';

abstract class CartState {
  final List<int> cartItem;
  const CartState({@required this.cartItem});

  @override
  List<Object> get props => [];
}

class ProductAdded extends CartState {
  final List<int> cartItem;
  const ProductAdded({@required this.cartItem}) : super(cartItem: cartItem);

  @override
  List<Object> get props => [cartItem];
  @override
  String toString() => 'ProductAdded { todos: $cartItem }';
}

Write business logic to add and remove products into the cartItems and emit the respective state. The actual list of items in the cart is maintained at the BLoC level.

class CartBloc extends Bloc<CartEvent, CartState> {
  CartBloc() : super(ProductAdded(cartItem: []));

  final List<int> _cartItems = [];
  List<int> get items => _cartItems;

  @override
  Stream<CartState> mapEventToState(CartEvent event) async* {
    if (event is AddProduct) {
      _cartItems.add(event.productIndex);
      yield ProductAdded(cartItem: _cartItems);
    } else if (event is RemoveProduct) {
      _cartItems.remove(event.productIndex);
      yield ProductRemoved(cartItem: _cartItems);
    }
  }
}

Next, wrap the scaffold widget inside BlocProvider.

BlocProvider is a Flutter widget that makes any BLoC available to the entire widget tree below it. In our case, any widget in between Home (top) and ProductTile (bottom) can have access to the cart, so no need to pass the cart data from the top of the widget tree to the bottom.

BlocProvider(
    create: (_) => CartBloc(),
    child: Scaffold(
      appBar: CartCounter(),
      body: ProductList(),
    ));

Wrap the cart icon and product list inside the BlocBuilderBlocBuilder simply rebuilds the widget inside it upon receiving the new states from the BLoC.

// Cart icon
BlocBuilder<CartBloc, CartState>(builder: (_, cartState) {
  List<int> cartItem = cartState.cartItem;
  return Positioned(
    left: 30,
    child: Container(
      padding: EdgeInsets.all(5),
      decoration: BoxDecoration(
          borderRadius: BorderRadius.circular(10),
          color: Colors.red),
      child: Text(
        '${cartItem.length}',
        style: TextStyle(fontWeight: FontWeight.bold),
      ),
    ),
  );
}),
//Product list
 BlocBuilder<CartBloc, CartState>(builder: (_, cartState) {
  List<int> cart = cartState.cartItem;
  return LayoutBuilder(builder: (context, constraints) {
    return GridView.builder(
      itemCount: 100,
      itemBuilder: (context, index) => ProductTile(
        itemNo: index,
        cart: cart,
      ),
      gridDelegate: SliverGridDelegateWithFixedCrossAxisCount(
        crossAxisCount: constraints.maxWidth > 700 ? 4 : 1,
        childAspectRatio: 5,
      ),
    );
  });
});

Note: The BlocBuilder for CartBloc is added only in two places because we only want these two widgets to rebuild when something happen at CartBloc. This approach of only refreshing widgets that are required significantly reduces the number of unnecessary redraws.

The next step is to shoot events to CartBloc for adding and removing items in the cart. BlocProvider.of<CartBloc>(context) finds the nearest instance of CartBloc in the widget tree and adds the events to it:

IconButton(
  key: Key('icon_$itemNo'),
  icon: cart.contains(itemNo)
      ? Icon(Icons.shopping_cart)
      : Icon(Icons.shopping_cart_outlined),
  onPressed: () {
    !cart.contains(itemNo)
        ? BlocProvider.of<CartBloc>(context).add(AddProduct(itemNo))
        : BlocProvider.of<CartBloc>(context).add(RemoveProduct(itemNo));
  },
)

Now replace BlocBuilder with BlocConsumerBlocConsumer allows us to rebuild the widget and react to the states. It should be only used when you want to rebuild the widget and also perform some action.

For our example, we want to refresh the list and show a snackbar whenever a product is added or removed from the cart:

BlocConsumer<CartBloc, CartState>(
listener: (context, state) { 
  Scaffold.of(context).showSnackBar(
    SnackBar(
      content: Text(
          state is ProductAdded ? 'Added to cart.' : 'Removed from cart.'),
      duration: Duration(seconds: 1),
    ),
  );
}, 
builder: (_, cartState) {
  List<int> cart = cartState.cartItem;
  return LayoutBuilder(builder: (context, constraints) {
    return GridView.builder();
  });
});

Optionally, if you want to reduce some boilerplate code and the sequence of the states doesn’t matter to you, try Cubit. Here is what CartCubit would look like:

class CartCubit extends Cubit<CartState> {
  CartCubit() : super(ProductAdded(cartItem: []));

  final List<int> _cartItems = [];
  List<int> get items => _cartItems;

  void add(int productIndex) {
    _cartItems.add(productIndex);
    emit (ProductAdded(cartItem: _cartItems));
  }

  void remove(int productIndex) {
    _cartItems.remove(productIndex);
    emit (ProductRemoved(cartItem: _cartItems));
  }
}

Note: Replace CartBloc with CartCubit throughout the code and fire the events as shown below:

onPressed: () {
  !cart.contains(itemNo)
      ? BlocProvider.of<CartCubit>(context).add(itemNo)
      : BlocProvider.of<CartCubit>(context).remove(itemNo);
},

The output is the same but with improved state management:

Cart Updating

Conclusion

Having a solid BLoC architecture in place leads to a good separation of concerns. Although using the BLoC pattern requires more code than using setState, it makes the code more readable, scalable, and testable.

In this tutorial, we covered the basics of using the BLoC pattern in Flutter and walked through a practical example to highlight the benefits of using BLoC for state management in Flutter over the setState approach.

You can find the complete source code for this example on GitHub.

#flutter #mobile-apps #web-development #design-pattern

What is GEEK

Buddha Community

How to Use the BLoC Design Pattern for State Management in Flutter

Google's Flutter 1.20 stable announced with new features - Navoki

Flutter Google cross-platform UI framework has released a new version 1.20 stable.

Flutter is Google’s UI framework to make apps for Android, iOS, Web, Windows, Mac, Linux, and Fuchsia OS. Since the last 2 years, the flutter Framework has already achieved popularity among mobile developers to develop Android and iOS apps. In the last few releases, Flutter also added the support of making web applications and desktop applications.

Last month they introduced the support of the Linux desktop app that can be distributed through Canonical Snap Store(Snapcraft), this enables the developers to publish there Linux desktop app for their users and publish on Snap Store.  If you want to learn how to Publish Flutter Desktop app in Snap Store that here is the tutorial.

Flutter 1.20 Framework is built on Google’s made Dart programming language that is a cross-platform language providing native performance, new UI widgets, and other more features for the developer usage.

Here are the few key points of this release:

Performance improvements for Flutter and Dart

In this release, they have got multiple performance improvements in the Dart language itself. A new improvement is to reduce the app size in the release versions of the app. Another performance improvement is to reduce junk in the display of app animation by using the warm-up phase.

sksl_warm-up

If your app is junk information during the first run then the Skia Shading Language shader provides for pre-compilation as part of your app’s build. This can speed it up by more than 2x.

Added a better support of mouse cursors for web and desktop flutter app,. Now many widgets will show cursor on top of them or you can specify the type of supported cursor you want.

Autofill for mobile text fields

Autofill was already supported in native applications now its been added to the Flutter SDK. Now prefilled information stored by your OS can be used for autofill in the application. This feature will be available soon on the flutter web.

flutter_autofill

A new widget for interaction

InteractiveViewer is a new widget design for common interactions in your app like pan, zoom drag and drop for resizing the widget. Informations on this you can check more on this API documentation where you can try this widget on the DartPad. In this release, drag-drop has more features added like you can know precisely where the drop happened and get the position.

Updated Material Slider, RangeSlider, TimePicker, and DatePicker

In this new release, there are many pre-existing widgets that were updated to match the latest material guidelines, these updates include better interaction with Slider and RangeSliderDatePicker with support for date range and time picker with the new style.

flutter_DatePicker

New pubspec.yaml format

Other than these widget updates there is some update within the project also like in pubspec.yaml file format. If you are a flutter plugin publisher then your old pubspec.yaml  is no longer supported to publish a plugin as the older format does not specify for which platform plugin you are making. All existing plugin will continue to work with flutter apps but you should make a plugin update as soon as possible.

Preview of embedded Dart DevTools in Visual Studio Code

Visual Studio code flutter extension got an update in this release. You get a preview of new features where you can analyze that Dev tools in your coding workspace. Enable this feature in your vs code by _dart.previewEmbeddedDevTools_setting. Dart DevTools menu you can choose your favorite page embed on your code workspace.

Network tracking

The updated the Dev tools comes with the network page that enables network profiling. You can track the timings and other information like status and content type of your** network calls** within your app. You can also monitor gRPC traffic.

Generate type-safe platform channels for platform interop

Pigeon is a command-line tool that will generate types of safe platform channels without adding additional dependencies. With this instead of manually matching method strings on platform channel and serializing arguments, you can invoke native class and pass nonprimitive data objects by directly calling the Dartmethod.

There is still a long list of updates in the new version of Flutter 1.2 that we cannot cover in this blog. You can get more details you can visit the official site to know more. Also, you can subscribe to the Navoki newsletter to get updates on these features and upcoming new updates and lessons. In upcoming new versions, we might see more new features and improvements.

You can get more free Flutter tutorials you can follow these courses:

#dart #developers #flutter #app developed #dart devtools in visual studio code #firebase local emulator suite in flutter #flutter autofill #flutter date picker #flutter desktop linux app build and publish on snapcraft store #flutter pigeon #flutter range slider #flutter slider #flutter time picker #flutter tutorial #flutter widget #google flutter #linux #navoki #pubspec format #setup flutter desktop on windows

Brain  Crist

Brain Crist

1603616400

Flutter Bloc State Management

A flutter bloc state management series that will walk you through from all the basics of streams to advance state management tools like flutter_bloc/bloc package

Let’s start by understanding what we mean by state management and why should we care about it in the first place.

What Exactly Is State management ?

In simple words, state means data or the current information the user can see or manipulate.

For eg: Interface controls such as text fields, OK buttons, radio buttons, etc. To maintain these state of data like weather a button is pressed or not what is the current text in the text field or is a toggle button on or off, These data which user generally see or interacts with or generates on some event is called the state and the term used for maintaining all these information(state) is called state management.

The problem :

State management can become very messy when the application grows, simple tools like setState in flutter can’t be the solution for managing large changes at once and tools like inherited widget can create a lot of boilerplate code.

The Solution :

To overcome the above problem we can simply use tools like flutter_bloc/bloc these packages are created by the community are pretty useful for reducing boilerplate code and can be very easy to implement.

Before going deep into the flutter_bloc package we need to make our basics clear these basics includes :

_:: _streams

:: cubit

:: bloc

Streams :

A stream is a sequence of asynchronous data. Streams are just like water hose which have a sink and a drain, Which we can use to provide and retrieve data from streams. To fully understand the concept of bloc we will first need to understand the core features and basic application of streams in Dart.

As we know the basic definition of streams lets generate our own stream using the yield keyword.

Image for post

Image for post

using yield to generate stream’s

In the above example, we have a function getRandomNumberStream this function is present in “lib\streamGenerators.dart” (It’s better to clone the repo and take a look at the structure of the program) which output streams we have specified that by using *async. **Then we have a Future.delayed() which delays our execution for the first run for 1000 ms and then 500 ms for every other subsequent execution. Then we output(yield) the value.

What** yield **does it basically output the data in the form of a stream, So this function is going to be our go-to for all our need for streams in this first series.

Now let me brief about all the basic functions that are available with streams.

  • .map: .map helps us to map the event that we are getting from the stream by passing them to a function. ex
StreamGenerators.getRandomNumberStream(10).map((event) => "This event --$event-- is mapped");

op:
This event --$0-- is mapped
This event --$1-- is mapped
This event --$2-- is mapped
This event --$3-- is mapped
This event --$4-- is mapped
  • .take: .take will only take the first N values and drain the rest of the values. ex

#bloc #flutter-widget #flutter-state-management #flutter-bloc #flutter

Terry  Tremblay

Terry Tremblay

1598396940

What is Flutter and why you should learn it?

Flutter is an open-source UI toolkit for mobile developers, so they can use it to build native-looking** Android and iOS** applications from the same code base for both platforms. Flutter is also working to make Flutter apps for Web, PWA (progressive Web-App) and Desktop platform (Windows,macOS,Linux).

flutter-mobile-desktop-web-embedded_min

Flutter was officially released in December 2018. Since then, it has gone a much stronger flutter community.

There has been much increase in flutter developers, flutter packages, youtube tutorials, blogs, flutter examples apps, official and private events, and more. Flutter is now on top software repos based and trending on GitHub.

Flutter meaning?

What is Flutter? this question comes to many new developer’s mind.

humming_bird_dart_flutter

Flutter means flying wings quickly, and lightly but obviously, this doesn’t apply in our SDK.

So Flutter was one of the companies that were acquired by **Google **for around $40 million. That company was based on providing gesture detection and recognition from a standard webcam. But later when the Flutter was going to release in alpha version for developer it’s name was Sky, but since Google already owned Flutter name, so they rename it to Flutter.

Where Flutter is used?

Flutter is used in many startup companies nowadays, and even some MNCs are also adopting Flutter as a mobile development framework. Many top famous companies are using their apps in Flutter. Some of them here are

Dream11

Dream11

NuBank

NuBank

Reflectly app

Reflectly app

Abbey Road Studios

Abbey Road Studios

and many more other apps. Mobile development companies also adopted Flutter as a service for their clients. Even I was one of them who developed flutter apps as a freelancer and later as an IT company for mobile apps.

Flutter as a service

#dart #flutter #uncategorized #flutter framework #flutter jobs #flutter language #flutter meaning #flutter meaning in hindi #google flutter #how does flutter work #what is flutter

Flutter App

Flutter App

1641357547

How to Build out a Shopping Cart App using BLoC Pattern & Flutter

In this application, you learn how to build out a shopping cart application using the #flutter #bLoC #pattern with beautiful UI. Take a look. Happy Coding! 💗💗

source code: https://github.com/smrity24/shopping-cart-app-using-bloc-pattern 
Become A Patreon to get full Source code: https://www.patreon.com/learnflutterwithsmrity 

Subscribe: https://www.youtube.com/c/LearnFlutterWithSmrity/featured 

#flutter #bloc 

Samanta  Moore

Samanta Moore

1623835440

Builder Design Pattern

What is Builder Design Pattern ? Why we should care about it ?

Starting from **Creational Design Pattern, **so wikipedia says “creational design pattern are design pattern that deals with object creation mechanism, trying to create objects in manner that is suitable to the situation”.

The basic form of object creations could result in design problems and result in complex design problems, so to overcome this problem Creational Design Pattern somehow allows you to create the object.

Builder is one of the** Creational Design Pattern**.

When to consider the Builder Design Pattern ?

Builder is useful when you need to do lot of things to build an Object. Let’s imagine DOM (Document Object Model), so if we need to create the DOM, We could have to do lot of things, appending plenty of nodes and attaching attributes to them. We could also imagine about the huge XML Object creation where we will have to do lot of work to create the Object. A Factory is used basically when we could create the entire object in one shot.

As **Joshua Bloch (**He led the Design of the many library Java Collections Framework and many more) – “Builder Pattern is good choice when designing the class whose constructor or static factories would have more than handful of parameters

#java #builder #builder pattern #creational design pattern #design pattern #factory pattern #java design pattern