Flutter BLoC (Business Logic Component)
Published: 2024-07-09 15:36:00

Flutter BLoC (Business Logic Component) architecture is a design pattern used to manage state in a Flutter application. It separates the business logic from the UI, making the code more modular and testable. Here's an overview of how to implement the BLoC architecture in Flutter.

### 1. Setting Up Your Flutter Project

First, create a new Flutter project if you don't already have one:

```bash
flutter create my_bloc_app
cd my_bloc_app
```

### 2. Add Dependencies

Add the `flutter_bloc` and `equatable` packages to your `pubspec.yaml` file:

```yaml
dependencies:
  flutter:
    sdk: flutter
  flutter_bloc: ^8.0.1
  equatable: ^2.0.3
```

Run `flutter pub get` to install the dependencies.

### 3. Creating a BLoC

Let's create a counter example to demonstrate the BLoC architecture.

#### 3.1 Define Events

Create a file `counter_event.dart` in the `lib` directory:

```dart
import 'package:equatable/equatable.dart';

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

class Increment extends CounterEvent {}

class Decrement extends CounterEvent {}
```

#### 3.2 Define States

Create a file `counter_state.dart`:

```dart
import 'package:equatable/equatable.dart';

class CounterState extends Equatable {
  final int count;

  const CounterState(this.count);

  @override
  List<Object> get props => [count];
}
```

#### 3.3 Define BLoC

Create a file `counter_bloc.dart`:

```dart
import 'package:flutter_bloc/flutter_bloc.dart';
import 'counter_event.dart';
import 'counter_state.dart';

class CounterBloc extends Bloc<CounterEvent, CounterState> {
  CounterBloc() : super(CounterState(0)) {
    on<Increment>((event, emit) => emit(CounterState(state.count + 1)));
    on<Decrement>((event, emit) => emit(CounterState(state.count - 1)));
  }
}
```

### 4. Using the BLoC in the UI

#### 4.1 Provide the BLoC

In your `main.dart` file, wrap your `MaterialApp` with a `BlocProvider`:

```dart
import 'package:flutter/material.dart';
import 'package:flutter_bloc/flutter_bloc.dart';
import 'counter_bloc.dart';
import 'counter_event.dart';
import 'counter_state.dart';

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

class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return BlocProvider(
      create: (context) => CounterBloc(),
      child: MaterialApp(
        home: CounterPage(),
      ),
    );
  }
}
```

#### 4.2 Create the UI

Create a file `counter_page.dart`:

```dart
import 'package:flutter/material.dart';
import 'package:flutter_bloc/flutter_bloc.dart';
import 'counter_bloc.dart';
import 'counter_event.dart';
import 'counter_state.dart';

class CounterPage extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(title: Text('Counter')),
      body: BlocBuilder<CounterBloc, CounterState>(
        builder: (context, state) {
          return Center(
            child: Text('Count: ${state.count}', style: TextStyle(fontSize: 24)),
          );
        },
      ),
      floatingActionButton: Column(
        mainAxisAlignment: MainAxisAlignment.end,
        children: [
          FloatingActionButton(
            onPressed: () => context.read<CounterBloc>().add(Increment()),
            child: Icon(Icons.add),
          ),
          SizedBox(height: 8),
          FloatingActionButton(
            onPressed: () => context.read<CounterBloc>().add(Decrement()),
            child: Icon(Icons.remove),
          ),
        ],
      ),
    );
  }
}
```

### 5. Running the App

Now, you can run your app using:

```bash
flutter run
```

### Summary

In this example, you:

1. Created a BLoC (`CounterBloc`) that handles `Increment` and `Decrement` events and emits new states.
2. Defined events and states for the counter.
3. Provided the BLoC to the widget tree using `BlocProvider`.
4. Built the UI using `BlocBuilder` to respond to state changes and dispatch events.

This setup keeps your business logic separate from your UI, making your code more modular and easier to test.