Event based Bloc
Block Pattern

Part 5 – Flutter BLoC Tutorial: Event-Based BLoC with Events, States & emit()

🧠 What is Event-Based BLoC?

Unlike Cubit, the BLoC pattern uses events to trigger state changes, making it ideal when:

  • ✅ You have multiple event types
  • ✅ You want to separate UI actions from business logic
  • ✅ You’re dealing with asynchronous or complex workflows

🎯 Let’s Build a Subscriber App with BLoC


lib/
├── bloc/
│   ├── subscriber_bloc.dart
│   ├── subscriber_event.dart
│   └── subscriber_state.dart
└── main.dart

🔹 Step 1: Define Events

📁 lib/bloc/subscriber_event.dart



abstract class SubscriberEvent {}

class Subscribe extends SubscriberEvent {}

class Unsubscribe extends SubscriberEvent {}


🔹 Step 2: Define States

📁 lib/bloc/subscriber_state.dart




class SubscriberState {
  final int count;

  SubscriberState(this.count);
}




🔹 Step 3: Create the BLoC

📁 lib/bloc/subscriber_bloc.dart


import 'package:flutter_bloc/flutter_bloc.dart';
import 'subscriber_event.dart';
import 'subscriber_state.dart';

class SubscriberBloc extends Bloc<SubscriberEvent, SubscriberState> {
  SubscriberBloc() : super(SubscriberState(100)) {
    on((event, emit) {
      emit(SubscriberState(state.count + 1));
    });

    on((event, emit) {
      emit(SubscriberState(state.count > 0 ? state.count - 1 : 0));
    });
  }
}


🧩 UI Integration

🔸 Provide the BLoC

📍 In your main widget tree:


BlocProvider(
  create: (context) => SubscriberBloc(),
  child: SubscriberPage(),
)

🔸 Show the State

📍 Inside the widget build method:


BlocBuilder<SubscriberBloc, SubscriberState>(
  builder: (context, state) {
    final count = (state as SubscriberValue).count;
    return Text('Count: \$count', style: TextStyle(fontSize: 30));
  },
)

🔸 Trigger Events

📍 Buttons to interact with BLoC:


FloatingActionButton(
 onPressed: () {
                context.read().add(bscribe());
              },
  child: Icon(Icons.add),
),

FloatingActionButton(
 onPressed: () {
                context.read().add(Unsubscribe());
              },
  child: Icon(Icons.remove),
),

📍 Main.dart:


import 'package:flutter/material.dart';
import 'package:flutter_bloc/flutter_bloc.dart';
import 'bloc/subscriber_bloc.dart';
import 'bloc/subscriber_event.dart';
import 'bloc/subscriber_state.dart';

void main() {
  runApp(SubscriberApp());
}

class SubscriberApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      title: 'YouTube Subscriber Counter',
      theme: ThemeData(
        primarySwatch: Colors.red,
      ),
      home: BlocProvider(
        create: (_) => SubscriberBloc(),
        child: SubscriberPage(),
      ),
    );
  }
}

class SubscriberPage extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Text('YouTube Subscriber Counter'),
        centerTitle: true,
      ),
      body: BlocConsumer<SubscriberBloc, SubscriberState>(
        listener: (context, state) {
          if (state.count == 0) {
            ScaffoldMessenger.of(context).showSnackBar(
              SnackBar(
                content: Text('No more subscribers left!'),
                backgroundColor: Colors.red,
                duration: Duration(seconds: 2),
              ),
            );
          } else {
            ScaffoldMessenger.of(context).showSnackBar(
              SnackBar(
                content: Text('Subscribers: ${state.count}'),
                duration: Duration(milliseconds: 800),
              ),
            );
          }
        },
        builder: (context, state) {
          return Center(
            child: Column(
              mainAxisAlignment: MainAxisAlignment.center,
              children: [
                Icon(Icons.subscriptions, size: 100, color: Colors.red),
                SizedBox(height: 20),
                Text(
                  '${state.count} Subscribers',
                  style: TextStyle(fontSize: 32, fontWeight: FontWeight.bold),
                ),
              ],
            ),
          );
        },
      ),
      floatingActionButton: Padding(
        padding: const EdgeInsets.only(right: 20.0),
        child: Row(
          mainAxisAlignment: MainAxisAlignment.end,
          children: [
            FloatingActionButton(
              heroTag: 'unsubscribe',
              onPressed: () {
                context.read().add(Unsubscribe());
              },
              child: Icon(Icons.remove),
              tooltip: 'Unsubscribe',
              backgroundColor: Colors.redAccent,
            ),
            SizedBox(width: 12),
            FloatingActionButton(
              heroTag: 'subscribe',
              onPressed: () {
                context.read().add(Subscribe());
              },
              child: Icon(Icons.add),
              tooltip: 'Subscribe',
              backgroundColor: Colors.green,
            ),
          ],
        ),
      ),
    );
  }
}



✅ Summary

Concept Description
Event What happened (e.g., Increment)
State The current UI/data state
on<Event>() Event handler in your BLoC
emit() Sends new state to the UI
BlocBuilder Rebuilds UI on state change
context.read().add() Triggers events from the UI

🚀 Coming Up Next:

Part 6 – BlocListener and BlocConsumer
Learn how to listen to BLoC changes (e.g., showing Snackbars or Alerts) and combine listeners + UI builders.

Leave a Reply

Your email address will not be published. Required fields are marked *