BLoC: Events, States & Cubit
BLoC (Business Logic Component) is a state management pattern for Flutter that separates business logic and state from the UI layer. Events flow IN, states flow OUT -- widgets dispatch events and rebuild in response to emitted states, without containing business logic themselves.
Cubit: The Simple Case
import 'package:flutter_bloc/flutter_bloc.dart';
// Cubit: exposes methods directly for changing state -- simpler
// than full Bloc's event-in/state-out stream architecture
class CounterCubit extends Cubit<int> {
CounterCubit() : super(0);
void increment() => emit(state + 1);
void decrement() => emit(state - 1);
}Bloc: Named Events for More Complex Logic
// Distinct, mutually-exclusive states -- makes an invalid combination
// like "loading AND error simultaneously" structurally impossible,
// unlike a single class with boolean isLoading/hasError flags
sealed class LoginState {}
class LoginInitial extends LoginState {}
class LoginLoading extends LoginState {}
class LoginSuccess extends LoginState { final User user; LoginSuccess(this.user); }
class LoginFailure extends LoginState { final String message; LoginFailure(this.message); }
sealed class LoginEvent {}
class LoginSubmitted extends LoginEvent {
final String email, password;
LoginSubmitted(this.email, this.password);
}
class LoginBloc extends Bloc<LoginEvent, LoginState> {
final AuthService authService;
LoginBloc(this.authService) : super(LoginInitial()) {
on<LoginSubmitted>((event, emit) async {
emit(LoginLoading());
try {
final user = await authService.login(event.email, event.password);
emit(LoginSuccess(user));
} catch (e) {
emit(LoginFailure(e.toString()));
}
});
}
}Unidirectional Data Flow
Event -> Bloc -> State -> UI, one consistent direction. This predictable cycle makes it much easier to reason about how and why state changed at any point, compared to widgets directly mutating shared state from arbitrary places.
Keep your own version of these notes — editable, searchable, and organised by your stack.
Start free