Flutter: BLoC vs. Cubit

image.png

In BLoC architecture or BLoC pattern, there are two terms often involved viz: bloc and cubit. The Cubit is a subset of the famous implementation of BLoC Pattern; it abandons the concept of Events and simplifies the way of emitting states.

bloc

image.png

When we use BLoC, there’s two important things: “Events” and “States”. That means that when we send an “Event” we can receive one or more “States”, and these “States” are sent in a stream.

What’s a Cubit?

image.png

When we use cubit, we can only send “states” and to trigger these states we can do it by calling a function (like actions). It’s a class that stores an observable state, the observation is powered by Streams but in such a friendly way that it is not necessary to know reactive programming.

Like I mentioned, Cubit is a subset of Bloc (Bloc extends Cubit) so you can think of Cubit as a simplified Bloc which has less functionality. Blocs are more powerful than Cubits but Cubits are more simple.

The recommended thing is to use Cubit for simpler methods and evolve to Bloc, because you don't need an excavator (Bloc) to remove a sand shovel.

Track Events and States

Sometimes you want to track what “event/state” was sent, or maybe the relation between an “event” and the “state”. This helps us to make the debugging easier, understand the relation between event and state, verify the sequence of the data flow, and check transitions. For large applications sometimes could be difficult to know which “event” triggers certain “states” also report this thing could be useful for analytics.

One of the major difference between BLoC and Cubit is this:

BLoC is event-driven and Cubit is not.

BLoC: Because it is event-driven we can know what event it triggered, what’s the current state and the next one. We can override “onTransition” and check how these events are coming and how these states change; another way is using a BLoC observer.

Cubit: As we know, cubit is not event-driven. We call functions (like actions) to send these “states”, so we can track which state were emitted and not events because here there are not events. We can track state overriding the “onChange” function; another way is using a BLoC observer.

In conclusion..

For things like API Calls, Database Access, etc. you can use BLoC or Cubit, both works. Cubit is a subset of Bloc; so, it reduces complexity. Cubit eliminates the event classes. Cubit uses emit rather than yield to emit state. Since emit works synchronously, you can ensure that the state is updated in the next line. Cubit is perfectly suitable to any app scale and anyone saying one scales better than the other is ill-informed.

You have to choose between traceability with an event-driven architecture which comes with boiler plate vs more traditional code. One advantage of event driven architectures is that events can be used by 0 or many handlers, the emitter does not care. The disadvantage is the indirection and extra boiler plate.

0
Subscribe to my newsletter

Read articles from Pranesh Pyara Shrestha directly inside your inbox. Subscribe to the newsletter, and don't miss out.

Written by

Pranesh Pyara Shrestha
Pranesh Pyara Shrestha

Cross-Platform Mobile Engineer (Flutter) | Cloud & DevOps Solutions Architect