BLoC (Business Logic Component) tách logic khỏi UI theo một chiều: UI gửi event vào, BLoC xử lý rồi phát ra state mới, UI chỉ vẽ theo state.
Bộ package thường dùng là bloc + flutter_bloc.
sealed class LoginEvent {}
final class LoginSubmitted extends LoginEvent {
LoginSubmitted(this.email, this.password);
final String email, password;
}
class LoginBloc extends Bloc<LoginEvent, LoginState> {
LoginBloc(this.repo) : super(LoginInitial()) {
on<LoginSubmitted>((event, emit) async {
emit(LoginLoading());
try {
await repo.login(event.email, event.password);
emit(LoginSuccess());
} catch (e) {
emit(LoginFailure('$e'));
}
});
}
final AuthRepository repo;
}Phía UI: BlocProvider cung cấp bloc xuống cây, BlocBuilder vẽ theo state, BlocListener cho việc chỉ chạy một lần (điều hướng, hiện SnackBar).
Cubit là bản gọn: không có event, gọi method rồi emit(state). Dùng Cubit cho màn đơn giản; dùng Bloc khi cần truy vết event hoặc xử lý luồng event (debounce ô tìm kiếm, bỏ request cũ bằng event transformer).
Vì sao hay bị hỏi: nhiều team chọn BLoC làm chuẩn cho dự án lớn vì mọi thay đổi state đều đi qua event → dễ log, dễ test bằng bloc_test, nhiều người cùng code vẫn theo một khuôn.
Lưu ý: state nên bất biến và so sánh được (Equatable hoặc freezed); emit một state bằng với state hiện tại sẽ bị bỏ qua và UI không rebuild. Nhược điểm chính là boilerplate — màn đơn giản dùng Cubit hoặc Riverpod sẽ gọn hơn.