Chapters

Hide chapters

Real-World Flutter by Tutorials

First Edition · Flutter 3.3 · Dart 2.18 · Android Studio or VS Code

Real-World Flutter by Tutorials

Section 1: 16 chapters
Show chapters Hide chapters

5. Managing Complex State With Blocs
Written by Edson Bueno

Heads up... You’re accessing parts of this content for free, with some sections shown as scrambled text.

Heads up... You’re accessing parts of this content for free, with some sections shown as scrambled text.

Unlock our entire catalogue of books and courses, with a Kodeco Personal Plan.

Unlock now

Two chapters ago, you embarked on a journey to master state management with the bloc library. You started by using a Cubit — a simplified Bloc — to manage the quote details screen. Then, in the previous chapter, you consolidated that knowledge and demonstrated how far one could go with Cubits. You learned how to use Cubits to handle what’s perhaps the most common challenge in app development: form validation. Finally, this chapter is where you step up to the real thing: Blocs.

Now, if you think of Cubits as worse than Blocs, that’s actually not the case at all: Cubits can do 95% of what Blocs can do at 60% of the complexity — numbers taken from the same source that revealed 73.6% of all numbers are made up on the spot.

The point is: You don’t stop using Cubits once you know Blocs. If this was a shooter game, Cubits would be your handguns: lighter and easier to use, thus more effective for close combat. Yet, sometimes you just need a Bloc sniper rifle and don’t care about carrying the extra weight. But that’s enough metaphors for a “real-world” book…

In this chapter, you’ll learn how to:

  • Understand the difference between Cubits and Blocs, and what that looks like in the code.
  • Communicate with a Bloc.
  • Create a Bloc.
  • Generate, manipulate and consume Streams.
  • Implement a full-fledged search bar with advanced techniques such as debouncing.
  • Determine the exact situations where you should pick Blocs over Cubits.

While going through this chapter, you’ll work on the starter project from this chapter’s assets folder.

Differentiating Between Cubits and Blocs

Both Cubits and Blocs do only two things:

  • Take in events.
  • Emit states.

Processes Events Sends events Interacts with the app User Receives visual feedback Emits states Cubit/Bloc

Events come in, and states go out. Nothing new so far, right?

Now, get this tattooed on your brain: The only difference between Cubits and Blocs is how they take in those UI events. Nothing else.

As you’ve seen from the last two chapters, Cubits take in events through functions you define inside them and then call from your widgets. For example:

UpvoteIconButton(
  onTap: () {
    if (quote.isUpvoted == true) {
      cubit.unvoteQuote();
    } else {
      cubit.upvoteQuote();
    }
  },
  // Omitted code.
)

Blocs, on the other hand, come pre-baked with an add() function you have to use for all events. For example:

UpvoteIconButton(
  onTap: () {
    if (quote.isUpvoted == true) {
      bloc.add(QuoteDetailsUnvoted());
    } else {
      bloc.add(QuoteDetailsUpvoted());
    }
  },
  // Omitted code.
)

Since you have to use one function for all your events, you differentiate between the events through the object you pass in as the add() function’s argument. You specify the type of these objects when you define the Bloc, as in:

QuoteDetailsBloc Bloc QuoteDetailsEvent, QuoteDetailsState < > { } //Ommitted code. extends class { } < > //Ommitted code. extends class QuoteDetailsCubit Cubit QuoteDetailsState vs.

This means that when using Blocs, besides having to create a state class — as you do for Cubits — you now have one extra level of complexity: creating an event class.

Throughout this chapter, though, you’ll see that this extra cost of using Blocs doesn’t come without benefits. Having all your events coming in through a single function gives you a whole lot more control over how to process these events. As a general rule, screens with search bars can benefit a lot from that.

For WonderWords specifically, the home screen is the ideal candidate for Blocs — lots of different events and a search bar — so that’s where your focus will be for the rest of this chapter.

Having gone through the last two chapters, creating state classes should no longer be a mystery to you. So, you’ll skip that part and dive right into the unknown territory: the event classes.

Creating Event Classes

Open the starter project and fetch the dependencies by running the make get command from the root directory. Ignore any errors in the code for now and open quote_list_event.dart inside the quote_list feature package.

{ } DoapeJozsMwig Hkaq QeebiGavxEdayl, GeabaNezbFwowo < > //Uvlagdey kitu. orbefpp zsuwk

CeeheCebbItekz CeivoFaxlUnepYecocabap WuemuCagmAxilArtesitazoy LoezeFohxNurxepMjKoquzepezTemzgal MaaciVevfNoycKaqaVumiuqcuh YoulaZiqrAmarCasusoraHicjnen - WoenaJatqXuitxcGocqSkahzon CiebiQohjMobfihvux DeuzeWihrDofNpoqroq

Forwarding the Events to the Bloc

Open quote_list_screen.dart, which lives under the same directory you’ve been working on.

Scaffolding the Bloc

Still in the same directory you’ve been working on, open quote_list_bloc.dart.

Fetching Data

Replace // TODO: Create a utility function that fetches a given page. with:

Receiving Events

Inside the _registerEventHandler() function, replace // TODO: Take in the events. with:

RaoriNuxnIwuvj HuipaLakyEgebNupezakeh TuotuFezyIwudEwnuwayeyib TiidaNevkTonsubWfSodabanuxLaffgad LieliNapzBocjYiqeTuxuuzfux JueroGajfOzucQizikadoBihqtag LiopeKazrYuixikQaqxjilMutcood LoaraJulyEfewsacaEhcaiyem MaiwaFivsObavObyimic JeavoXevqLeifwfLawtFbowqas XiawoXijkNewbicxub ZaoneHimtCupTxuhzez

Handling Individual Events

Scroll down and find // TODO: Handle QuoteListUsernameObtained.. Replace it with:

Controlling the Traffic of Events

Now, changing subjects, your home screen is in pretty good shape already, but have you tried using the search bar? You’d find two problems with it:

Knowing the Transformer Function

Get back to the code, and, continuing on your Bloc’s file, replace // TODO: Customize how events are processed. with:

Applying the Debouncing Effect

Pick up where you left off by replacing // TODO: Debounce search events. with:

Applying the Canceling Effect

By default, Blocs process all incoming events in parallel. It works extremely well for the majority of situations — so much so that this is how all Cubits work — but it ends up being a problem for search bars:

Jeoyym “qi” “taw” “tixo” Thofuhsugp Vuqo

Giecxf “we” “kil” “wuqu” Ljazebjuqj Cipa

wayrafpehm bfasaqt epanjj davbobyoljtx (sdoc’j vujueyh) kupoelvooh jcekitd inigfs rocaocseushr vdavxexhu ulloni uxw oxemsh idran xhixe it uxobn al dnadognevf dumqovyiwre wxikurd ompr bwo fiwill utehn oqx jakrah mqifoiig eriws jevsqupj

Key Points

  • You don’t stop using Cubits once you know Blocs; one isn’t better than the other.
  • The only difference between Cubits and Blocs is how they receive events from the UI layer.
  • While Cubits require you to create one function for each event, Blocs require you to create one class for each.
  • As a rule of thumb, default to Cubits for their simplicity. Then, if you find you need to control the traffic of events coming in, upgrade to Blocs.
  • If you don’t customize the transformer, your Bloc will perform just like a Cubit: processing events one by one as they arrive and not considering their order when handing over the results.
  • The ability to customize how events are processed is why you should pick a Bloc over a Cubit.
Have a technical question? Want to report a bug? You can ask questions and report bugs to the book authors in our official book forum here.
© 2026 Kodeco Inc.

You’re accessing parts of this content for free, with some sections shown as scrambled text. Unlock our entire catalogue of books and courses, with a Kodeco Personal Plan.

Unlock now