Summary - Bloc advanced
- Flutter course
- Advanced
- Lesson 10/69
- 4 min
Combine Bloc, event and state to make a login flow.
Login flow
In a login flow, Bloc, event and state work together. When the user presses the button, LoginSubmittedEvent is triggered; the Bloc receives it, first emits LoginLoading, then on completion transitions to LoginSuccess or LoginFailure. The UI uses BlocBuilder to show different widgets for each state.
class LoginBloc extends Bloc<LoginEvent, LoginState> {
LoginBloc() : super(LoginInitial()) {
on<LoginSubmittedEvent>((event, emit) async {
emit(LoginLoading());
await Future.delayed(Duration(seconds: 1));
emit(LoginSuccess('Ayşe'));
});
}
}Practice Write a complete login Bloc
Define LoginEvent and LoginSubmittedEvent. Write the LoginState abstract class with LoginInitial, LoginLoading, and LoginSuccess (holds a username) subclasses. LoginBloc should start with LoginInitial; its LoginSubmittedEvent handler should first emit LoginLoading, then after a short delay emit LoginSuccess('Ayşe'). In main, trigger the event, wait, and print the username on success.
Starter code
import 'package:bloc/bloc.dart';
// LoginEvent soyut sınıfı
// LoginSubmittedEvent alt sınıfı
// LoginState soyut sınıfı
// LoginInitial, LoginLoading, LoginSuccess alt sınıfları
// LoginSuccess: kullanıcı adı tutar
// LoginBloc sınıfını yaz
// başlangıç state LoginInitial
// event işleyici: önce Loading, sonra Success
void main() async {
// oluştur, event ekle, bekle, durumu yazdır
}Sample solution
import 'package:bloc/bloc.dart';
abstract class LoginEvent {}
class LoginSubmittedEvent extends LoginEvent {}
abstract class LoginState {}
class LoginInitial extends LoginState {}
class LoginLoading extends LoginState {}
class LoginSuccess extends LoginState {
final String user;
LoginSuccess(this.user);
}
class LoginBloc extends Bloc<LoginEvent, LoginState> {
LoginBloc() : super(LoginInitial()) {
on<LoginSubmittedEvent>((event, emit) async {
emit(LoginLoading());
await Future.delayed(Duration(milliseconds: 10));
emit(LoginSuccess('Ayşe'));
});
}
}
void main() async {
final bloc = LoginBloc();
bloc.add(LoginSubmittedEvent());
await Future.delayed(Duration(milliseconds: 50));
final state = bloc.state;
if (state is LoginSuccess) {
print(state.user);
}
}Expected output
Ayşe
Questions and answers
Review the lesson questions together with their answers. To test yourself, solve the lesson interactively.
1 What happens when the button is pressed in a login flow?
- The state becomes LoginSuccess immediately
- LoginSubmittedEvent is triggered and the Bloc processes it Correct answer
- BlocBuilder does not rebuild
- The event class is removed from memory
Explanation: When the button is pressed, a LoginSubmittedEvent is created and sent to the Bloc via bloc.add; the Bloc processes the event and produces state.
2 Emit loading state
on<LoginSubmittedEvent>((event, emit) async {
____(LoginLoading());
await Future.delayed(Duration(milliseconds: 10));
emit(LoginSuccess('Ayşe'));
});
on<LoginSubmittedEvent>((event, emit) async {
emit(LoginLoading());
await Future.delayed(Duration(milliseconds: 10));
emit(LoginSuccess('Ayşe'));
});
Explanation: Inside a handler you call emit to produce a new state; add is for adding events and is meaningless inside a handler.
3 Login flow parts
| Term | Meaning |
|---|---|
LoginSubmittedEvent |
User intent |
LoginLoading |
Waiting state |
LoginSuccess |
Success state |
on<LoginSubmittedEvent> |
Event handler |