Flutter
Challenge 2
Build a login flow with error handling via Bloc.
Challenge 2 - Login with Bloc
In this challenge you will build a login flow with a Bloc. A LoginEvent arrives, the LoginState becomes loading, then transitions to success or failure.
class LoginBloc extends Bloc<LoginEvent, LoginState> {
LoginBloc() : super(LoginInitial()) {
on<LoginSubmitted>((event, emit) async {
emit(LoginLoading());
emit(LoginSuccess());
});
}
}
Exercise Define LoginBloc
First define LoginEvent (abstract) and LoginSubmitted. Then define LoginState (abstract) and LoginInitial, LoginLoading, LoginSuccess. Define LoginBloc as Bloc<LoginEvent, LoginState>: constructor calls super(LoginInitial()), registers on<LoginSubmitted>, handler first does emit(LoginLoading()) then emit(LoginSuccess()). In main, create a LoginBloc instance and print state.runtimeType.
Show example solution
import 'package:flutter_bloc/flutter_bloc.dart';
abstract class LoginEvent {}
class LoginSubmitted extends LoginEvent {}
abstract class LoginState {}
class LoginInitial extends LoginState {}
class LoginLoading extends LoginState {}
class LoginSuccess extends LoginState {}
class LoginBloc extends Bloc<LoginEvent, LoginState> {
LoginBloc() : super(LoginInitial()) {
on<LoginSubmitted>((event, emit) async {
emit(LoginLoading());
emit(LoginSuccess());
});
}
}
void main() {
final bloc = LoginBloc();
print(bloc.state.runtimeType);
bloc.close();
}
Exercise Add the LoginSubmitted event
The following classes are provided: LoginEvent, LoginSubmitted, LoginState, LoginInitial, LoginLoading, LoginSuccess, LoginBloc. In main, create a LoginBloc instance, call bloc.add(LoginSubmitted()), wait 100ms, print bloc.state.runtimeType, then call bloc.close().
Show example solution
import 'package:flutter_bloc/flutter_bloc.dart';
abstract class LoginEvent {}
class LoginSubmitted extends LoginEvent {}
abstract class LoginState {}
class LoginInitial extends LoginState {}
class LoginLoading extends LoginState {}
class LoginSuccess extends LoginState {}
class LoginBloc extends Bloc<LoginEvent, LoginState> {
LoginBloc() : super(LoginInitial()) {
on<LoginSubmitted>((event, emit) async {
emit(LoginLoading());
emit(LoginSuccess());
});
}
}
void main() async {
final bloc = LoginBloc();
bloc.add(LoginSubmitted());
await Future.delayed(const Duration(milliseconds: 100));
print(bloc.state.runtimeType);
bloc.close();
}
Test yourself
-
What runs when a new event arrives in a Bloc?
- createState
- dispose
- build method
- The handler registered with on<Event>
Show answer
The handler registered with on<Event> — The Bloc routes the incoming event to the handler registered with on<Event>; the handler updates state via emit.
-
Transition to success state with emit
emit(____);
Show answer
emit(LoginSuccess);
-
Bloc matches
- Bloc
- Event and state manager
- event
- User action
- state
- Screen state
- emit
- Updates state
Next lesson: Challenge 3