Wednesday, February 4, 2026
HomeFlutterbloc example with dummy api for login screen

bloc example with dummy api for login screen

Here’s a complete Flutter BLoC example showing how to implement a login screen with a dummy API (simulated network call).
This includes:
LoginBloc (handles login events and states)
LoginRepository (fake API call)
LoginScreen (UI with BlocBuilder & BlocListener)


🧱 Folder structure

lib/
 ├── bloc/
 │    ├── login_bloc.dart
 │    ├── login_event.dart
 │    └── login_state.dart
 ├── repository/
 │    └── login_repository.dart
 ├── main.dart
 └── login_screen.dart

🧩 Step 1: Add Dependencies

In your pubspec.yaml:

dependencies:
  flutter:
    sdk: flutter
  flutter_bloc: ^9.1.1
  equatable: ^2.0.5


⚙️ Step 2: Create Repository (dummy API)

// lib/repository/login_repository.dart
import 'dart:async';

class LoginRepository {
  Future<bool> login(String email, String password) async {
    await Future.delayed(const Duration(seconds: 2)); // simulate network delay
    if (email == 'test@example.com' && password == '123456') {
      return true; // success
    } else {
      throw Exception('Invalid credentials');
    }
  }
}

🧠 Step 3: Create BLoC files

login_event.dart

// lib/bloc/login_event.dart
import 'package:equatable/equatable.dart';

abstract class LoginEvent extends Equatable {
  @override
  List<Object> get props => [];
}

class LoginButtonPressed extends LoginEvent {
  final String email;
  final String password;

  LoginButtonPressed({required this.email, required this.password});

  @override
  List<Object> get props => [email, password];
}

login_state.dart

// lib/bloc/login_state.dart
import 'package:equatable/equatable.dart';

abstract class LoginState extends Equatable {
  @override
  List<Object> get props => [];
}

class LoginInitial extends LoginState {}
class LoginLoading extends LoginState {}
class LoginSuccess extends LoginState {}
class LoginFailure extends LoginState {
  final String message;
  LoginFailure(this.message);
  @override
  List<Object> get props => [message];
}

login_bloc.dart

// lib/bloc/login_bloc.dart
import 'package:flutter_bloc/flutter_bloc.dart';
import '../repository/login_repository.dart';
import 'login_event.dart';
import 'login_state.dart';

class LoginBloc extends Bloc<LoginEvent, LoginState> {
  final LoginRepository loginRepository;

  LoginBloc(this.loginRepository) : super(LoginInitial()) {
    on<LoginButtonPressed>(_onLoginButtonPressed);
  }

  Future<void> _onLoginButtonPressed(
      LoginButtonPressed event, Emitter<LoginState> emit) async {
    emit(LoginLoading());
    try {
      bool success = await loginRepository.login(event.email, event.password);
      if (success) {
        emit(LoginSuccess());
      }
    } catch (e) {
      emit(LoginFailure(e.toString().replaceAll('Exception: ', '')));
    }
  }
}

🖥️ Step 4: Create UI (login_screen.dart)

// lib/login_screen.dart
import 'package:flutter/material.dart';
import 'package:flutter_bloc/flutter_bloc.dart';
import 'bloc/login_bloc.dart';
import 'bloc/login_event.dart';
import 'bloc/login_state.dart';
import 'repository/login_repository.dart';

class LoginScreen extends StatelessWidget {
  final TextEditingController emailController = TextEditingController();
  final TextEditingController passwordController = TextEditingController();

  LoginScreen({super.key});

  @override
  Widget build(BuildContext context) {
    return BlocProvider(
      create: (_) => LoginBloc(LoginRepository()),
      child: Scaffold(
        appBar: AppBar(title: const Text('Login')),
        body: BlocListener<LoginBloc, LoginState>(
          listener: (context, state) {
            if (state is LoginSuccess) {
              ScaffoldMessenger.of(context).showSnackBar(
                const SnackBar(content: Text('Login Successful!')),
              );
            } else if (state is LoginFailure) {
              ScaffoldMessenger.of(context).showSnackBar(
                SnackBar(content: Text(state.message)),
              );
            }
          },
          child: Padding(
            padding: const EdgeInsets.all(16),
            child: Column(
              mainAxisAlignment: MainAxisAlignment.center,
              children: [
                TextField(
                  controller: emailController,
                  decoration: const InputDecoration(labelText: 'Email'),
                ),
                const SizedBox(height: 10),
                TextField(
                  controller: passwordController,
                  decoration: const InputDecoration(labelText: 'Password'),
                  obscureText: true,
                ),
                const SizedBox(height: 20),
                BlocBuilder<LoginBloc, LoginState>(
                  builder: (context, state) {
                    if (state is LoginLoading) {
                      return const CircularProgressIndicator();
                    }
                    return ElevatedButton(
                      onPressed: () {
                        final email = emailController.text.trim();
                        final password = passwordController.text.trim();
                        context.read<LoginBloc>().add(
                              LoginButtonPressed(
                                  email: email, password: password),
                            );
                      },
                      child: const Text('Login'),
                    );
                  },
                ),
              ],
            ),
          ),
        ),
      ),
    );
  }
}

🚀 Step 5: Run App (main.dart)

// lib/main.dart
import 'package:flutter/material.dart';
import 'login_screen.dart';

void main() {
  runApp(const MyApp());
}

class MyApp extends StatelessWidget {
  const MyApp({super.key});

  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      debugShowCheckedModeBanner: false,
      title: 'BLoC Login Demo',
      theme: ThemeData(primarySwatch: Colors.blue),
      home: LoginScreen(),
    );
  }
}

✅ Test Credentials

Use these to test:

Email: test@example.com
Password: 123456

RELATED ARTICLES

LEAVE A REPLY

Please enter your comment!
Please enter your name here

Most Popular

Recent Comments