Understanding Cubit in Flutter: A Simplified Approach to State Management
Introduction
Hey, Flutter devs! ???? After diving deep into Provider and Bloc, let’s simplify things a bit with Cubit—a lightweight state management solution built on top of Bloc.
If you love the power of Bloc but find the event-state mechanism a bit too much for some cases, then Cubit is for you!
What is Cubit?
Cubit is part of the Bloc package, but instead of using events, it directly exposes functions to change state. This makes it more straightforward, cleaner, and easier to manage for simpler state management needs.
With Cubit, you:
? Call functions instead of dispatching events.
? Emit new states directly.
? Avoid boilerplate code compared to Bloc.
Getting Started with Cubit
Let’s build a simple counter app using Cubit.
Step 1: Add Cubit to Your Project
Add the flutter_bloc package (Cubit is included inside Bloc):
dependencies:
flutter:
sdk: flutter
flutter_bloc: ^8.1.3
flutter pub get
Step 2: Create the Cubit Class
Create a file counter_cubit.dart:
import 'package:bloc/bloc.dart';
class CounterCubit extends Cubit<int> {
CounterCubit() : super(0); // Initial state is 0
void increment() => emit(state + 1);
void decrement() => emit(state - 1);
}
How it Works?
Step 3: Provide Cubit to Your App
Wrap your app in a BlocProvider inside main.dart:
import 'package:flutter/material.dart';
import 'package:flutter_bloc/flutter_bloc.dart';
import 'counter_cubit.dart';
void main() {
runApp(
BlocProvider(
create: (context) => CounterCubit(),
child: MyApp(),
),
);
}
class MyApp extends StatelessWidget {
@override
Widget build(BuildContext context) {
return MaterialApp(
home: CounterScreen(),
);
}
}
Step 4: Build the UI
Create counter_screen.dart:
import 'package:flutter/material.dart';
import 'package:flutter_bloc/flutter_bloc.dart';
import 'counter_cubit.dart';
class CounterScreen extends StatelessWidget {
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(title: Text('Cubit Counter Example')),
body: Center(
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: [
Text('You have pushed the button this many times:'),
BlocBuilder<CounterCubit, int>(
builder: (context, count) {
return Text(
'$count',
style: Theme.of(context).textTheme.headline4,
);
},
),
],
),
),
floatingActionButton: Row(
mainAxisAlignment: MainAxisAlignment.end,
children: [
FloatingActionButton(
onPressed: () => context.read<CounterCubit>().increment(),
tooltip: 'Increment',
child: Icon(Icons.add),
),
SizedBox(width: 10),
FloatingActionButton(
onPressed: () => context.read<CounterCubit>().decrement(),
tooltip: 'Decrement',
child: Icon(Icons.remove),
),
],
),
);
}
}
How it Works?
Here's your next article for your LinkedIn newsletter, covering Cubit, a simplified alternative to Bloc.
Understanding Cubit in Flutter: A Simplified Approach to State Management
By Wael Abdallah Full Stack Developer @Callem.ai || Mobile Developer @CarNet || Software Engineering Student
Introduction
Hey, Flutter devs! ???? After diving deep into Provider and Bloc, let’s simplify things a bit with Cubit—a lightweight state management solution built on top of Bloc.
If you love the power of Bloc but find the event-state mechanism a bit too much for some cases, then Cubit is for you!
What is Cubit?
Cubit is part of the Bloc package, but instead of using events, it directly exposes functions to change state. This makes it more straightforward, cleaner, and easier to manage for simpler state management needs.
With Cubit, you: ? Call functions instead of dispatching events. ? Emit new states directly. ? Avoid boilerplate code compared to Bloc.
Bloc vs. Cubit: What’s the Difference?
FeatureBlocCubitUses events?? Yes? NoSimplicity? More boilerplate? Less boilerplateState UpdatesEvent → Bloc → StateFunction → emit(State)Best ForLarge-scale appsMedium to small apps
Getting Started with Cubit
Let’s build a simple counter app using Cubit.
Step 1: Add Cubit to Your Project
Add the flutter_bloc package (Cubit is included inside Bloc):
yaml
CopyEdit
dependencies: flutter: sdk: flutter flutter_bloc: ^8.1.3 # Latest version as of (1/10/2024)
Run:
sh
CopyEdit
flutter pub get
Step 2: Create the Cubit Class
Create a file counter_cubit.dart:
dart
CopyEdit
import 'package:bloc/bloc.dart'; class CounterCubit extends Cubit<int> { CounterCubit() : super(0); // Initial state is 0 void increment() => emit(state + 1); void decrement() => emit(state - 1); }
How it Works?
Step 3: Provide Cubit to Your App
Wrap your app in a BlocProvider inside main.dart:
dart
CopyEdit
import 'package:flutter/material.dart'; import 'package:flutter_bloc/flutter_bloc.dart'; import 'counter_cubit.dart'; void main() { runApp( BlocProvider( create: (context) => CounterCubit(), child: MyApp(), ), ); } class MyApp extends StatelessWidget { @override Widget build(BuildContext context) { return MaterialApp( home: CounterScreen(), ); } }
Step 4: Build the UI
Create counter_screen.dart:
dart
CopyEdit
import 'package:flutter/material.dart'; import 'package:flutter_bloc/flutter_bloc.dart'; import 'counter_cubit.dart'; class CounterScreen extends StatelessWidget { @override Widget build(BuildContext context) { return Scaffold( appBar: AppBar(title: Text('Cubit Counter Example')), body: Center( child: Column( mainAxisAlignment: MainAxisAlignment.center, children: [ Text('You have pushed the button this many times:'), BlocBuilder<CounterCubit, int>( builder: (context, count) { return Text( '$count', style: Theme.of(context).textTheme.headline4, ); }, ), ], ), ), floatingActionButton: Row( mainAxisAlignment: MainAxisAlignment.end, children: [ FloatingActionButton( onPressed: () => context.read<CounterCubit>().increment(), tooltip: 'Increment', child: Icon(Icons.add), ), SizedBox(width: 10), FloatingActionButton( onPressed: () => context.read<CounterCubit>().decrement(), tooltip: 'Decrement', child: Icon(Icons.remove), ), ], ), ); } }
How it Works?
When Should You Use Cubit?
Use Cubit when:
? You need better structure than setState(), but don’t want the complexity of Bloc.
? Your app has simple state transitions.
? You want less boilerplate.
Conclusion
Cubit is a powerful, simple, and lightweight alternative to Bloc. If you're managing state in a structured but minimal way, Cubit is a fantastic choice. It offers less boilerplate and more direct state management while keeping your Flutter app scalable and maintainable.
?? But Bloc and Cubit aren’t the only state management solutions in Flutter! In the next article, we’ll explore Riverpod, another modern and flexible approach that simplifies dependency injection and state management. Stay tuned!
?? Follow me on GitHub for more Flutter content: GitHub - Wael Abdallah
?? Learn more about Cubit on Pub.dev: flutter_bloc
Let’s keep building awesome Flutter apps! ????