Getting Started with Cubit ?
What you will learn in this ?
Getting Started with Cubit ?
What you will learn in this ?
This article assumes you already practicing Flutter and have basic programming experience. It’s not a deep dive into Bloc — instead, think of it as a cheat sheet to get started with Cubit. We’ll focus only on how to update state in the UI using Cubit, and we’ll also look at the different Bloc builders (BlocBuilder, BlocSelector) since they work the same way with both Cubit and Bloc.
Open your VS Code Terminal and run these two command
flutter pub add flutter_bloc
flutter pub add equatable
flutter pub get
Lets start with State Class . There are two way to write states in Cubit and Different people prefer different types . They both have their Pros and Cons.
Type 1 .
[embed]
Type 2.
[embed]
Type 1 (single state class + flags/nullable fields):
- Less boilerplate.
- All values live in one class → changes just copy the old object with updates.
- You must allow null or defaults, since not all fields apply in every case.
- As long as one state class has fewer than ~20 fields, performance impact is negligible.
Type 2 (abstract + multiple state classes):
- More boilerplate.
- Each state carries only what it needs (Loading has nothing, Success has data, etc.).
- More human-readable → by looking at state classes, you instantly know possible UI states.
✅ So:
Choose Type 1 for quick/simple flows or for small projects.
Choose Type 2 for clarity and long-term maintainability
Now lets start with Cubit. This is where we will be writing business logic .
Cubit of Type 1.
[embed]
Type 2 .
[embed]
As you can see, the Type 2 Cubit is cleaner and simpler since we directly emit specific states without juggling nullable fields or flags.
Also note that you can trigger initial API calls inside the Cubit constructor by emitting a state right after initialization.
Let’s start with a simple Login UI. Instead of diving into every widget, here’s a quick grouped list to make things easier to understand:
Layout & Structure (single-child containers)
. Container, Padding, Center, SafeArea, SingleChildScrollView
Layout & Structure (multi-child containers)
Row, Column, ListView, ExpansionTile, Card, SliverAppBar, Scaffold
Input & Interaction
TextFormField, ElevatedButton, InkWell, Ink ,
App Wrappers
MaterialApp, CupertinoApp
This grouping helps you quickly see which widgets control layout, which handle input, and which wrap your app.Play with these widgets and its enough to get started with UI.
Type 1 Login Screen
[embed]
Type 2 Login
[embed]
In both Type 1 and Type 2 we build the UI with BlocBuilder — Type 1 checks state.isLoading == true, while Type 2 checks state is LoginLoading. Calling Cubit functions is the same in both cases. The difference comes with TextEditingController: in Type 1 it’s outside the builder (safe), while in Type 2 it’s inside the builder (can reset on rebuild). A cleaner alternative is to keep the controllers inside the Cubit and access them with context.read<LoginCubit>().usernameController.
[embed]
TextEditingController is managed by the Cubit, not the UI.
UI stays clean (StatelessWidget).Lifecycle handled (dispose() in cubit).
When it comes to Flutter, the most important thing is how state updates the UI and which parts get rebuilt.
BlocBuilder rebuilds every time a new state is emitted. That means even if only one field changes, the whole widget tree inside BlocBuilder gets rebuilt.But what if you just want to toggle a checkbox? Do you really want to rebuild the entire TextField and Button too?
That’s where BlocSelector shines.
BlocSelector listens to just one field of the state.It rebuilds only the widget that depends on that field, not the whole tree.
In Type 2 (multiple small states), you avoid some of this because each state represents one scenario.
In Type 1 (one big state with many fields), using BlocSelector is super important so you don’t rebuild everything unnecessarily.
⚡ Pro tip: If you’re new to Flutter and want to see rebuilds in action, just add a print("WidgetName rebuilt") inside every build method. You’ll instantly see how often and which widgets are being rebuil
[embed]
One of the most important how are you providing the cubit ,
[embed]
In this example, the BlocProvider creates the cubit inside MyApp. This means that by the time we reach the LoginScreen, the cubit is already available in the widget tree, and you can access it directly with context.read.
Remember: where you create a cubit (or any object) defines its lifecycle.
- If you provide a cubit in Screen A and then push Screen B on top of it, the cubit from Screen A will continue to live as long as Screen A stays in the navigation stack.
- If you pop back from Screen B to Screen A, the instance of Screen B (and its cubit) is destroyed.
I’ve tried to cover the basics of Cubit here, but there’s much more you can explore: adding coding rules, using BlocListener, streams, bloc. I’ll dive into those in my next article.
메타데이터
- post_id
- ba13891dce9e
- slug
- getting-started-with-cubit-ba13891dce9e
- url
- https://medium.com/@moesandar675/getting-started-with-cubit-ba13891dce9e
- canonical_url
- https://medium.com/@moesandar675/getting-started-with-cubit-ba13891dce9e
- author_url
- https://medium.com/@moesandar675
- status
- ok
- fetched_at
- 2026-06-24 16:30:55