Modern implementation of the Original BLoC

Overview

stream_bloc

Modern implementation of the Original BLoC

About

This package contains a modern (bloc package version 8.0.0+) implementation of the Original, Stream/generator-based BLoC with several modifications and convenience extras.

Motivation

After the 7.2.0 version update, the bloc has changed. Generators and the signature method mapEventToState were replaced with method-based pattern-matching using the on method and its argument handler. This approach is defiantly usable and solves a particular bug of the Dart language itself, but it lacks a few things.

  1. Power of streams. They can be transformed natively using a vast choice of transformers, but with the new bloc, streams are hidden under the hood and are not "first-class citizens".
  2. Power of generators. They allow to asynchronously return multiple values, including other streams. The new version emulates their behavior using higher-order functions.
  3. New on approach makes freezed basically useless. It is possible to register just a single handler, but it negates the whole point of the on handlers.

This package brings back Original bloc with all the benefits, whilst maintaining 100% compatibility with bloc and flutter_bloc packages. The StreamBlocs can be used with all flutter_bloc widgets; they implement the same interfaces.

Overview

If you are familiar with the bloc before the 8.0.0/7.2.0 you are familiar with StreamBloc – the central class of this package. Documentation for previous bloc's versions can be used for this packages besides a few modifications that are listed in the next section.

StreamBloc uses a central event-processing method called mapEventToStates to convert a single Event to a Stream of States that are emitted asynchronously. Official Bloc can be directly translated to StreamBloc as described below.

It is highly advised to use freezed package. The following example is a demonstration and should not be considered a "Best practice" for StreamBloc

abstract class CounterEvent {} // Shared counter event type

class Increment implements CounterEvent {} // Increment counter event

class Decrement implements CounterEvent {} // Decrement counter event

class OnCounterBloc extends Bloc<CounterEvent, int> { // Official Bloc – `on`s
  OnCounterBloc() : super(0) {
    on<Increment>((event, emit) => emit(state + 1));
    on<Decrement>((event, emit) => emit(state - 1));
  }
}

class StreamCounterBloc extends StreamBloc<CounterEvent, int> { // StreamBloc – `mapEventToStates`
  StreamCounterBloc() : super(0);

  @override
  Stream<int> mapEventToStates(CounterEvent event) async* {
    if (event is Increment) {
      yield state + 1;
    } else if (event is Decrement) {
      yield state - 1;
    }
  }
}

Modifications

There are three main differences from the Original bloc.

  1. mapEventToState is renamed to mapEventToStates. The method returns an asynchronous sequence of states – not a single state.

  2. It is not possible to emit a new state without it being a response to a certain event. StreamBloc does not implement Emittable and does not have an emit method. The original bloc has its method because both Cubit and Bloc are descendants of the same base class, but emit should not be used within a Bloc. It is marked as visible for testing, but it is always a good idea to test a whole instead of its parts.

  3. Bloc can emit identical states consequentially. The output stream of the StreamBloc is not distinct because of two main reasons

    • flutter_bloc's BlocListener/BlocConsumer may be interested in any new emitted state, even if the state had not changed
    • stream.map(...)/stream.where(...) (essentially BlocBuilder and/or BlocSelector) applied to stream.distinct() removes the guarantee of uniques event in the stream, making the distinct redundant; it should be applied last, not first.

Extras

The package also offers a single convenience mixin BlocLifecycleMixin which makes Bloc-to-Bloc communications easier. It offers four methods: listenToStream, listenToStreamable, reactToStream and reactToStreamable. Below is an example of its usage.

enum EventA { eventA }

class BlocA extends StreamBloc<EventA, int> {
  BlocA() : super(0);

  @override
  Stream<int> mapEventToStates(EventA event) => Stream.value(1);
}

enum EventB { eventB }

class BlocB extends StreamBloc<EventB, int> with BlocLifecycleMixin<EventB> {
  BlocB(BlocA blocA) : super(0) {
    /// Will print every new state of this Bloc to the console.
    listenToStream(stream, print);

    /// Will add [EventB.eventB] to this bloc every time BlocA emits any state.
    reactToStreamable<int>(blocA, (blocAState) => EventB.eventB);
  }

  @override
  Stream<int> mapEventToStates(EventB event) => Stream.value(1);
}

All methods return an instance of StreamSubscription which can be canceled by hand if desired, but it is optional – it will be canceled any way on the closing of a Bloc that mixes in BlocLifecycleMixin

You might also like...

Flutter bloc cubit test knowdge - Flutter bloc cubit test knowdge

Flutter Bloc Simple Api This project is using weather api for featch data and di

Jan 3, 2022

Flutter bloc infinite list - A sample application to learn flutter bloc the correct way

flutter_bloc_infinite_list A sample application to learn flutter bloc the correc

Aug 22, 2022

Flutter bloc example - An app for State management using BLoC pattern in Flutter

Flutter bloc example - An app for State management using BLoC pattern in Flutter

Flutter BLoC My first app for State management using BLoC pattern in Flutter Col

Jun 16, 2022

An example of "reactive/streaming repository" as a solution for BLoC to BLoC communication

An example of

Reactive Repositories An example of listening to a Stream from repository layer (instead of explicitly using get/fetch) as a solution for BLoC to BLoC

Jan 3, 2023

Weather app using Bloc architecture pattern & generic HTTP client with interface implementation and much more for more detail read Readme

Weather app using Bloc architecture pattern & generic HTTP client with interface implementation and much more for more detail read Readme

weather Weather application for current weather, hourly forecast for 48 hours, Daily forecast for 7 days and national weather alerts. How to Run Insta

Oct 29, 2022

Get It - Simple direct Service Locator that allows to decouple the interface from a concrete implementation and to access the concrete implementation from everywhere in your App. Maintainer: @escamoteur

Get It - Simple direct Service Locator that allows to decouple the interface from a concrete implementation and to access the concrete implementation from everywhere in your App. Maintainer: @escamoteur

❤️ Sponsor get_it This is a simple Service Locator for Dart and Flutter projects with some additional goodies highly inspired by Splat. It can be used

Jan 1, 2023

A simple PokeDex App with Modern UI created using Flutter and Dart and using API from PokeApi.

A simple PokeDex App with Modern UI created using Flutter and Dart and using API from PokeApi.

FlutterDex FlutterDex A simple PokeDex App created using Flutter and Dart and using API from PokeApi. UI Design inspired by : Home Screen Pokedex iOS

Jan 1, 2023

A GraphQL client for Flutter, bringing all the features from a modern GraphQL client to one easy to use package. Built after react apollo

Flutter GraphQL Table of Contents Flutter GraphQL Table of Contents About this project Installation Usage GraphQL Provider [Graphql Link and Headers]

Nov 9, 2022

Fluent System Icons are a collection of familiar, friendly and modern icons from Microsoft.

Fluent System Icons are a collection of familiar, friendly and modern icons from Microsoft.

Fluent UI System Icons Fluent UI System Icons are a collection of familiar, friendly and modern icons from Microsoft. Icon List View the full list of

Dec 29, 2022
Comments
  • 0.5.1 and 0.5.2 versions - transformEvents + MergeStream issue

    0.5.1 and 0.5.2 versions - transformEvents + MergeStream issue

    BLoC skipping events in case of using transformEvents + MergeStream as shown below:

    @override
      Stream<Transition<BlocEvent, BlocState>> transformEvents(
        Stream<BlocEvent> events,
        TransitionFunction<BlocEvent, PartsState> transitionFn,
      ) {
        final nonDebounceStream = events.where((event) => event is! FilterEvent);
        final debounceStream = events //
            .where((event) => event is FilterEvent)
            .debounceTime(const Duration(milliseconds: 200));
    
        return super.transformEvents(
          MergeStream([
            nonDebounceStream,
            debounceStream,
          ]),
          transitionFn,
        );
      }
    
    bug 
    opened by zs-dima 1
  • BlocObserver in the old style

    BlocObserver in the old style

    It would be nice to be able to set BlocObserver without using Zone, as it was before:

    Bloc.observer = CounterObserver();

    Looking at the current api it would look something like this:

    StreamBlocObserver.current = CounterObserver();

    The essence of the problem

    opened by mit-73 1
Owner
Yakov Karpov
Yakov Karpov
Raden Saleh 20 Aug 12, 2023
This is a JazzCash UI clone ( Modern Wallet App in Pakistan), implementing modern app bar animmation. One can take a concept of making app bar with animation.

jazzcash_ui This is a JazzCash UI clone ( Modern Wallet App in Pakistan), implementing modern app bar animmation. One can take a concept of making app

null 9 Nov 27, 2022
Petrus Nguyễn Thái Học 193 Dec 29, 2022
This repository contains Collection of UIs made using Flutter. Original Design of all the UIs were created by someone else. I tried to recreate those UIs using Flutter

Flutter-UIs-Collection This repository contains Collection of UIs made using Flutter. Original Design of all the UIs were created by someone else. I t

Mohak Gupta 45 Nov 26, 2022
A flutter widget which renders its child outside the original widget hierarchy.

overlay_container A flutter widget which renders its child outside the original widget hierarchy. Demo. This demo is present as an example here. You c

Mustansir Zia 30 Jun 10, 2022
Simple & Beautiful App (Tool) made in Flutter to Download Media from YouTube. Based on the original SongTube App repository.

songtube A new Flutter project. Getting Started This project is a starting point for a Flutter application. A few resources to get you started if this

SongTube 11 Dec 18, 2022
This is the UI of Furniture App made using Flutter SDK. The original design was made by someone else in dribble and I tried to create the screens of that UI using Flutter

Furniture App - Responsive Flutter UI Watch it on YouTube Responsive UI Fetch Data From API Custom Loading Indicator Packages we are using: flutter_sv

null 6 Dec 3, 2022
Raden Saleh 53 Jul 27, 2023
An extension to the bloc state management library which automatically persists and restores bloc states.

⚠️ Attention: This repository has been moved to https://github.com/felangel/bloc and is now read-only! An extension to the bloc state management libra

Felix Angelov 189 Nov 17, 2022
Notes-bloc-flutter - Proyecto para administrar tareas implementando patrón bloc

notes_bloc A new Flutter project. Getting Started This project is a starting point for a Flutter application. A few resources to get you started if th

Arnold Rodriguez 0 Jan 9, 2022