What is Bloc ?
Bloc (Business Logic Components) is one of the patterns recommended y Google. It helps you separate your business logic from UI. It’s also a pattern that separates responsibilities in application and helps you write easily testable code. You can check out other patterns recommended by Google here.
Bloc contains of three structures. These are Events Class, States Class and Bloc Class. Now let’s examine these in more detail.

1. Events:
Events represent the operations we want to perform in the application. Consider a contacts application, in this case events would be GetUsers, UpdateUser, DeleteUser etc. There is an abstract class for events, and other events that we will use inherit from this abstract class.
You need to create your own events according to the action you want to perform in the application.
2. States:
States represent the situations that will be found in the application. It is used to determine what to do in application in which situation. For the contacts app there could be UsersInitial, UsersLoading, UsersLoaded and UsersError etc.
3. Bloc:
We can think of Bloc Class as an intermediate class. It connects Events and States. When an event is triggered, which function will be called and with states the application will transition to are determined in the Bloc Class.
Bloc Usage
I developed a project using Bloc. This project has a screen. On this screen, you can randomly fetch characters from The Last Airbender. I developed the project with Clean Architecture, but I only explain the usage of block in this story. You can read my story about Clean Architecture in detail here. I used The Last Airbender API while developing the project.
Filling Example
Firstly I created core, config and features folders. Then I created characters folder in features folder for feature of fetch characters. Finally I created data, domain and presentation folders in characters folder.
I created bloc folder in features folder. This is because Bloc is used for the application’s business logic.
I added the files; events, state and bloc which are the three parts of Bloc.

Code Example
First I determined the states as CharactersInitial, CharactersLoading, CharactersError and CharactersLoaded and I created CharactersState as abstract class. Then I gave inheritance from CharactersState to other states.
part of 'characters_bloc.dart';
abstract class CharactersState {}
class CharactersInitial extends CharactersState {}
class CharactersLoading extends CharactersState {}
class CharactersLoaded extends CharactersState {
CharacterEntity character;
CharactersLoaded({required this.character});
}
class CharactersError extends CharactersState {
String? errorMessage;
CharactersError(this.errorMessage);
}
Secondly I created an abstract class for events. Since we will only be fetching characters in this application, I only created the GetCharacter event. And I gave inheritance from CharactersEvent class to GetCharacters class.
part of 'characters_bloc.dart';
abstract class CharactersEvent {}
class GetCharacters extends CharactersEvent {}
I gave inheritance from Bloc to CharactersBloc and I added events to constructer method of class. Then I created getCharacters function for fetch data. In this function, I triggered situations according to the API result.
part 'characters_event.dart';
part 'characters_state.dart';
class CharactersBloc extends Bloc<CharactersEvent,CharactersState> {
final GetCharacterUseCase _getCharactersUseCase;
CharactersBloc(this._getCharactersUseCase) : super(CharactersInitial()){
on<GetCharacters>(getCharacters);
}
Future<void> getCharacters(GetCharacters event, Emitter<CharactersState> emit) async {
emit(CharactersLoading());
final dataState = await _getCharactersUseCase.call(null);
if(dataState is DataSuccess){
emit(CharactersLoaded(character: dataState.data!));
} else if(dataState is DataFailed){
emit(CharactersError(dataState.exception!.message));
}
}
}
Finally, I coded to CharactersPage. I used BlocBuilder for listen to states. This is because when state changed I could return relevant function.
_buildBloc() {
return BlocBuilder(
bloc: _bloc,
builder: (BuildContext context, state) {
if(state is CharactersLoading){
return _showLoadingAnimation();
} else if(state is CharactersLoaded){
return _buildCharactersList(state);
} else if(state is CharactersError){
return _buildErrorView(state);
} else {
return _buildInitialView();
}
},
);
}
When screen loaded I triggered GetCharacters event.
@override
void initState() {
super.initState();
_bloc.add(GetCharacters());
}