Ответ
BLoC (Business Logic Component) — это архитектурный паттерн для управления состоянием в Flutter-приложениях, построенный на реактивных потоках (Streams). Его основная цель — отделить бизнес-логику от слоя представления (UI), что делает код предсказуемым, тестируемым и легко отслеживаемым.
Ключевые компоненты:
- События (Events): Входные данные, которые описывают, что произошло (например, нажатие кнопки
CounterIncrementPressed). - BLoC: Центральный компонент, который принимает поток событий, обрабатывает их с помощью бизнес-логики и преобразует в поток состояний. Он реализует класс
Bloc<Event, State>. - Состояния (States): Выходные данные, которые описывают как должен выглядеть UI в ответ на событие (например,
CounterState(count: 5)).
Практический пример — счётчик:
// 1. Определяем события
abstract class CounterEvent {}
class IncrementCounterEvent extends CounterEvent {}
// 2. Определяем состояния
abstract class CounterState {
final int count;
const CounterState(this.count);
}
class CounterInitialState extends CounterState {
CounterInitialState() : super(0);
}
class CounterUpdatedState extends CounterState {
const CounterUpdatedState(int count) : super(count);
}
// 3. Создаём BLoC
class CounterBloc extends Bloc<CounterEvent, CounterState> {
CounterBloc() : super(CounterInitialState()) {
// Регистрируем обработчик для события IncrementCounterEvent
on<IncrementCounterEvent>((event, emit) {
// Бизнес-логика: увеличиваем счётчик на 1
emit(CounterUpdatedState(state.count + 1));
});
}
}
// 4. Используем в UI с помощью BlocBuilder
BlocBuilder<CounterBloc, CounterState>(
builder: (context, state) {
return Column(
children: [
Text('Count: ${state.count}'),
ElevatedButton(
onPressed: () => context.read<CounterBloc>().add(IncrementCounterEvent()),
child: const Text('Increment'),
),
],
);
},
)
Почему это важно и когда использовать:
- Предсказуемость: Состояние изменяется только в ответ на явные события, что упрощает отладку.
- Тестируемость: Бизнес-логика в BLoC изолирована от UI и легко покрывается unit-тестами.
- Масштабируемость: Отлично подходит для сложных экранов с множеством взаимосвязанных состояний.
- Недостаток: По сравнению с более простыми решениями (как
CubitилиProvider), требует написания большего количества boilerplate-кода (отдельные классы для событий и состояний).