Define and use a BLoC
BLoC (Business Logic Component) is a state management pattern for Flutter applications. It helps separate business logic from UI components, making your code more testable and maintainable.
Basic Concepts
The BLoC pattern involves three main components:
- Events - Input actions that the bloc responds to
- States - Output that represents the UI state
- BLoC - Business logic that converts events to states
Implementation Steps
1. Add Dependencies
// In your pubspec.yaml
dependencies:
flutter_bloc: ^8.1.3 # Check for the latest version
2. Create State Class
// Define all possible states
abstract class CounterState {}
class CounterInitial extends CounterState {}
class CounterLoaded extends CounterState {
final int count;
CounterLoaded(this.count);
}
3. Create Event Class
// Define all possible events
abstract class CounterEvent {}
class IncrementEvent extends CounterEvent {}
class DecrementEvent extends CounterEvent {}
4. Create BLoC Class
import 'package:flutter_bloc/flutter_bloc.dart';
class CounterBloc extends Bloc<CounterEvent, CounterState> {
CounterBloc() : super(CounterInitial()) {
on<IncrementEvent>((event, emit) {
if (state is CounterInitial) {
emit(CounterLoaded(1));
} else if (state is CounterLoaded) {
final currentState = state as CounterLoaded;
emit(CounterLoaded(currentState.count + 1));
}
});
on<DecrementEvent>((event, emit) {
if (state is CounterLoaded) {
final currentState = state as CounterLoaded;
emit(CounterLoaded(currentState.count - 1));
}
});
}
}
5. Provide and Consume the BLoC
import 'package:flutter/material.dart';
import 'package:flutter_bloc/flutter_bloc.dart';
void main() {
runApp(MyApp());
}
class MyApp extends StatelessWidget {
@override
Widget build(BuildContext context) {
return BlocProvider(
create: (context) => CounterBloc(),
child: MaterialApp(
home: CounterPage(),
),
);
}
}
class CounterPage extends StatelessWidget {
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(title: Text('Counter Example')),
body: Center(
child: BlocBuilder<CounterBloc, CounterState>(
builder: (context, state) {
if (state is CounterInitial) {
return Text('Press the button to start counting');
} else if (state is CounterLoaded) {
return Text('Count: ${state.count}');
}
return Text('Unknown state');
},
),
),
floatingActionButton: Column(
mainAxisAlignment: MainAxisAlignment.end,
crossAxisAlignment: CrossAxisAlignment.end,
children: [
FloatingActionButton(
child: Icon(Icons.add),
onPressed: () => context.read<CounterBloc>().add(IncrementEvent()),
),
SizedBox(height: 10),
FloatingActionButton(
child: Icon(Icons.remove),
onPressed: () => context.read<CounterBloc>().add(DecrementEvent()),
),
],
),
);
}
}
Key Widgets
- BlocProvider: Provides a bloc to its children
- BlocBuilder: Rebuilds the UI based on bloc state changes
- BlocListener: Performs side effects based on state changes
- BlocConsumer: Combines BlocBuilder and BlocListener
- MultiBlocProvider: Provides multiple blocs to children
For more detailed documentation, refer to the flutter_bloc package documentation.