Video Tutorial
Lets understand this with an example
we are going to create a basic counter example here using bloc and cubit.
Here are the key differences between Bloc and Cubit in Flutter:
- Complexity:
- Bloc: Bloc is designed to handle more complex state management scenarios. It has support for handling events, side effects, and more advanced state transitions.
- Cubit: Cubit is a more lightweight version of Bloc. It’s intended for simpler state management scenarios where you don’t need to handle events explicitly.
- Event Handling:
- Bloc: Bloc has a dedicated
on(Event...)
method where you handle events and determine the new state based on those events. - Cubit: Cubit does not have a dedicated method for handling events. State changes are triggered directly using the
emit
method.
- Bloc: Bloc has a dedicated
- Direct State Changes:
- Bloc: State changes in Bloc are often indirect, happening in response to events.
- Cubit: Cubit allows for more direct state changes using the
emit
method. You explicitly callemit
to trigger state changes.
- Use Case:
- Bloc: Use Bloc when your application involves complex state transitions, side effects, or when you need fine-grained control over event handling.
- Cubit: Use Cubit for simpler scenarios where explicit event handling is not required, and you want a more straightforward way to manage state.
- Simplicity:
- Bloc: Bloc provides more structure and features, but this can lead to more boilerplate code.
- Cubit: Cubit is more concise and can be a good choice for scenarios where simplicity is a priority.
- Dependencies:
- Bloc: Bloc relies on the
bloc
package. - Cubit: Cubit relies on the
bloc
package as well, but it is a subset of Bloc, providing a simpler API.
- Bloc: Bloc relies on the
- Initialization:
- Bloc: Bloc requires more setup with the
mapEventToState
method. - Cubit: Cubit is simpler to initialize and use.
- Bloc: Bloc requires more setup with the
- Preferred Use:
- Bloc: Bloc is recommended for larger applications or scenarios where more advanced state management features are needed.
- Cubit: Cubit is recommended for simpler applications or when a lightweight state management solution is sufficient.
Both Bloc and Cubit are part of the broader Flutter Bloc library and adhere to the principles of reactive programming. Your choice between Bloc and Cubit will depend on the specific requirements of your application and your preferences for simplicity versus feature richness.
Counter – Cubit Example
import 'package:flutter/material.dart';
import 'package:flutter_bloc/flutter_bloc.dart';
// Cubit
class CounterCubit extends Cubit<int> {
CounterCubit() : super(0);
void increment() => emit(state + 1);
void decrement() => emit(state - 1);
}
void main() {
runApp(const MyApp());
}
class MyApp extends StatelessWidget {
const MyApp({super.key});
@override
Widget build(BuildContext context) {
return MaterialApp(
home: BlocProvider(
create: (context) => CounterCubit(),
child: const MyHomePage(),
),
);
}
}
class MyHomePage extends StatelessWidget {
const MyHomePage({super.key});
@override
Widget build(BuildContext context) {
final counterCubit = BlocProvider.of<CounterCubit>(context);
return Scaffold(
appBar: AppBar(
title: const Text('Cubit Counter App'),
),
body: Center(
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
const Text('Counter Value:'),
BlocBuilder<CounterCubit, int>(
builder: (context, state) {
return Text(
state.toString(),
style: const TextStyle(fontSize: 24),
);
},
),
],
),
),
floatingActionButton: Column(
mainAxisAlignment: MainAxisAlignment.end,
children: [
FloatingActionButton(
onPressed: () {
counterCubit.increment();
},
child: const Icon(Icons.add),
),
const SizedBox(height: 16),
FloatingActionButton(
onPressed: () {
counterCubit.decrement();
},
child: const Icon(Icons.remove),
),
],
),
);
}
}
Counter – Bloc Example
import 'package:flutter/material.dart';
import 'package:flutter_bloc/flutter_bloc.dart';
// Events
enum CounterEvent { increment, decrement }
// States
class CounterState {
final int count;
CounterState(this.count);
}
// Bloc
class CounterBloc extends Bloc<CounterEvent, CounterState> {
CounterBloc() : super(CounterState(0)) {
on<CounterEvent>((event, emit) {
if (event == CounterEvent.increment) {
emit(CounterState(state.count + 1));
}
if (event == CounterEvent.decrement) {
emit(CounterState(state.count - 1));
}
});
}
}
void main() {
runApp(const MyApp());
}
class MyApp extends StatelessWidget {
const MyApp({super.key});
@override
Widget build(BuildContext context) {
return MaterialApp(
home: BlocProvider(
create: (context) => CounterBloc(),
child: const MyHomePage(),
),
);
}
}
class MyHomePage extends StatelessWidget {
const MyHomePage({super.key});
@override
Widget build(BuildContext context) {
final counterBloc = BlocProvider.of<CounterBloc>(context);
return Scaffold(
appBar: AppBar(
title: const Text('Bloc Counter App'),
),
body: Center(
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
const Text('Counter Value:'),
BlocBuilder<CounterBloc, CounterState>(
builder: (context, state) {
return Text(
state.count.toString(),
style: const TextStyle(fontSize: 24),
);
},
),
],
),
),
floatingActionButton: Column(
mainAxisAlignment: MainAxisAlignment.end,
children: [
FloatingActionButton(
onPressed: () {
counterBloc.add(CounterEvent.increment);
},
child: const Icon(Icons.add),
),
const SizedBox(height: 16),
FloatingActionButton(
onPressed: () {
counterBloc.add(CounterEvent.decrement);
},
child: const Icon(Icons.remove),
),
],
),
);
}
}
Explanation:
- Events and States:
CounterEvent
is an enumeration representing events like increment and decrement.CounterState
represents the state of the counter, holding the current count.
- CounterBloc:
CounterBloc
extendsBloc<CounterEvent, CounterState>
.- The constructor initializes the Bloc with an initial state of
CounterState(0)
. on<CounterEvent>
is used to define how the Bloc reacts to events. It emits a new state based on the event.
- MyApp:
- The root widget of the application where
BlocProvider
is used to provide theCounterBloc
to the widget tree.
- The root widget of the application where
- MyHomePage:
- Displays the current count and has two floating action buttons to trigger increment and decrement events.
BlocBuilder
listens to state changes and rebuilds the UI accordingly.
Differences between Bloc and Cubit:
- This example uses
Bloc
for state management. - If using
Cubit
, you would changeextends Bloc<CounterEvent, CounterState>
toextends Cubit<CounterState>
. - In this specific example, the difference between Bloc and Cubit might not be very apparent due to its simplicity. Bloc is generally chosen for more complex scenarios involving event handling and transitions. Cubit is preferred for simpler cases where direct state changes are sufficient.