Flutter Bloc

Saina - Jun 4 - - Dev Community

BLoC (Business Logic Component) separates business logic from UI in a Flutter application, ensuring a clean and testable codebase. It utilizes streams to handle events and states, allowing for a reactive approach to state management. By adopting BLoC, you can create scalable and maintainable applications that are easier to debug and test.

Key Components of BLoC

  • Event: Represents user actions or events within the app.

  • State: Represents the state of the UI based on events.

  • Bloc: Manages events and emits corresponding states.

  • BlocBuilder: Builds UI based on the current state.

  • BlocListener: Listens for state changes to perform side effects.

  • BlocProvider: Provides BLoC to the widget tree.

Creating a BLoC

Event: User Actions or Events
Events in BLoC are simple classes that represent user actions or events within the app. They are the triggers that cause the BLoC to react and emit new states. Events are dispatched to the BLoC using the add method.

abstract class CounterEvent {}

class IncrementEvent extends CounterEvent {}

class DecrementEvent extends CounterEvent {}

Enter fullscreen mode Exit fullscreen mode

In the above example, **IncrementEvent **and **DecrementEvent **are used to increase or decrease the counter.

State: UI State Based on Events
States are also simple classes that represent the UI's state. The BLoC emits new states in response to events. The UI rebuilds itself based on these states.

abstract class CounterState {}

class CounterInitial extends CounterState {
  final int counter;
  CounterInitial(this.counter);
}

Enter fullscreen mode Exit fullscreen mode

Here, CounterInitial holds the counter value and is the state managed by the BLoC.

Bloc: Manages Events and States
The Bloc class is where the magic happens. It handles incoming events, processes them, and emits new states. The Bloc class extends the Bloc base class provided by the flutter_bloc package.

import 'package:flutter_bloc/flutter_bloc.dart';

class CounterBloc extends Bloc<CounterEvent, CounterState> {
  CounterBloc() : super(CounterInitial(0)) {
    on<IncrementEvent>((event, emit) {
      emit(CounterInitial((state as CounterInitial).counter + 1));
    });
    on<DecrementEvent>((event, emit) {
      emit(CounterInitial((state as CounterInitial).counter - 1));
    });
  }
}

Enter fullscreen mode Exit fullscreen mode

In this example, the BLoC reacts to IncrementEvent and DecrementEvent by emitting a new state with the updated counter value.

BlocBuilder: Builds UI Based on State
BlocBuilder is a Flutter widget that rebuilds its UI in response to new states emitted by the BLoC. It listens to the BLoC and triggers a rebuild whenever a new state is emitted.

BlocBuilder<CounterBloc, CounterState>(
  builder: (context, state) {
    if (state is CounterInitial) {
      return Center(
        child: Text('Counter: ${state.counter}'),
      );
    }
    return Container();
  },
)

Enter fullscreen mode Exit fullscreen mode

BlocBuilder rebuilds the Text widget with the current counter value whenever the state changes.

BlocListener: Listens for State Changes
BlocListener is another Flutter widget that listens for state changes but does not rebuild the UI. Instead, it allows you to perform side effects such as showing a SnackBar.

BlocListener<CounterBloc, CounterState>(
  listener: (context, state) {
    if (state is CounterInitial) {
      ScaffoldMessenger.of(context).showSnackBar(
        SnackBar(content: Text('Counter: ${state.counter}')),
      );
    }
  },
  child: BlocBuilder<CounterBloc, CounterState>(
    builder: (context, state) {
      if (state is CounterInitial) {
        return Center(
          child: Text('Counter: ${state.counter}'),
        );
      }
      return Container();
    },
  ),
)

Enter fullscreen mode Exit fullscreen mode

BlocListener shows a SnackBar with the current counter value whenever the state changes.

BlocProvider: Provides BLoC to the Widget Tree
BlocProvider is a Flutter widget that provides an instance of the BLoC to the widget tree. It ensures that the BLoC can be accessed from any descendant widget.

void main() {
  runApp(
    BlocProvider(
      create: (context) => CounterBloc(),
      child: MyApp(),
    ),
  );
}
Enter fullscreen mode Exit fullscreen mode

BlocProvider wraps the MyApp widget, providing CounterBloc to the entire widget tree.

Conclusion

Understanding BLoC is essential for managing state in complex Flutter applications. With events, states, BlocBuilder, BlocListener, and BlocProvider, you can build scalable and maintainable apps. By following these examples, you can start using BLoC in your projects to improve code organization and maintainability.

. . . . . . .