BLoC — какво е това, Business Logic Component във Flutter

Автор: IT Sectr Публикувано: 2026-02-19 Време за четене: 7 мин

BLoC (Business Logic Component) — модел за управление на състоянието за Flutter, представен от Google през 2018 г. на DartConf. BLoC разделя бизнес логиката от потребителския интерфейс чрез реактивни потоци (Stream): UI изпраща Event, BLoC го обработва и връща нов State чрез Stream. Според данните от pub.dev, пакетът flutter_bloc е събрал над 11 хиляди харесвания и се използва в хиляди Flutter приложения.

Основни точки

  • Event — входен сигнал, описващ действието: натискане на бутон, зареждане на данни
  • State — изходно състояние на UI: данните са заредени, грешка, зареждане
  • Bloc — основен клас, който приема Event и връща State чрез Stream
  • Cubit — опростена версия на Bloc без Event, извикваща функции директно
  • BlocProvider — Flutter widget за инжектиране на Bloc в дървото от widget-и

Какво е BLoC?

BLoC (Business Logic Component) — архитектурен модел за Flutter, при който бизнес логиката е изнесена в отделен клас, изолиран от UI. BLoC получава входни данни чрез поток от събития (Event) и произвежда изходни данни чрез поток от състояния (State). Презентационният слой (Widget) само се абонира за потока State и визуализира UI, без никога да изпълнява бизнес логика директно.

Концепцията на BLoC се основава на реактивното програмиране и модела Observer. Всеки компонент на BLoC е отделен модул с ясен договор: известни са наборът от Event (какво може да се случи) и наборът от State (какво може да се покаже). Разработчикът не може "случайно" да промени състоянието от UI — само чрез конкретен Event. Това прави кода предвидим и тестваем.

Според проучването Flutter Community 2025, BLoC заема второ място по популярност сред решенията за управление на състоянието във Flutter след Provider. Основни предимства: строга типизация, изолация на логиката, вградена поддръжка на Stream, богата екосистема от помощни средства (BlocProvider, BlocListener, BlocSelector).

Архитектура на BLoC: Event → Bloc → State

Архитектурата на BLoC е изградена около три обекта: Event (вход), Bloc (обработчик) и State (изход). Widget изпраща Event чрез метода add(). Bloc приема Event в метода mapEventToState или on<Event>, изпълнява бизнес логика и произвежда нов State чрез yield. Widget получава State чрез Stream и се прерисува.

Dart
abstract class CounterEvent {}

class Increment extends CounterEvent {}
class Decrement extends CounterEvent {}

class CounterBloc extends Bloc<CounterEvent, int> {
  CounterBloc() : super(0);

  @override
  Stream<int> mapEventToState(CounterEvent event) async* {
    if (event is Increment) {
      yield state + 1;
    } else if (event is Decrement) {
      yield state - 1;
    }
  }
}

Безопасност на типовете: Bloc е параметризиран с два типа — Event и State. Компилаторът на Dart проверява, че Widget извиква само декларирани Event, а Bloc връща само декларирани State. Грешки по време на изпълнение от типа "Неизвестно действие" са изключени.

Close и Dispose: Bloc имплементира интерфейса Closeable. При унищожаване на widget-а, Bloc автоматично затваря Stream чрез метода close(). Изтичане на реактивни абонаменти е невъзможно — BlocProvider управлява жизнения цикъл на Bloc, свързвайки го с route или страница.

Bloc и Cubit: сравнение

Cubit — опростена имплементация на Bloc без Event, представена в пакета flutter_bloc 6.0. Cubit декларира методи директно вместо класове Event: increment(), fetchData(). Вътрешно Cubit използва същия механизъм, базиран на Stream, но скрива слоя Event. Това намалява boilerplate с 40-50% за прости сценарии.

ХарактеристикаBlocCubit
Класове EventЗадължителниНе са необходими
BoilerplateВисокНисък
Проследяване на действияЧрез тип EventСамо име на метод
Подходящ заСложни сценарииПрости състояния
АналитикаАвтоматична чрез EventРъчна

Кога да изберем Cubit: състояние с 2-3 варианта (loading, loaded, error), прости формуляри, броячи, UI състояния (отворено/затворено). Кога да изберем Bloc: сложна бизнес логика с множество действия: завършване на поръчка, авторизация, синхронизация на данни. Bloc предоставя детайлно проследяване на всяко действие чрез Event — всяко извикване се записва в BlocObserver.

BlocObserver — глобален наблюдател, който проследява всички Bloc и Cubit в приложението. Позволява записване на Event, State, грешки и преходи. Достатъчно е да свържете един екземпляр: Bloc.observer = AppBlocObserver(), и цялото проследяване на състоянието на приложението е достъпно централизирано.

BlocProvider и BlocBuilder

BlocProvider — InheritedWidget от flutter_bloc, който предоставя Bloc на дъщерните widget-и. При инициализация на widget-а, BlocProvider създава Bloc, а при унищожаване — го затваря автоматично чрез close(). BlocProvider може да бъде поставен на ниво MaterialApp (глобален Bloc) или на ниво конкретен route (локален Bloc).

Dart
BlocProvider(
  create: (context) => CounterBloc(),
  child: Column(
    children: [
      BlocBuilder<CounterBloc, int>(
        builder: (context, state) => Text('$state'),
      ),
      ElevatedButton(
        onPressed: () => context.read<CounterBloc>().add(Increment()),
        child: Text('+'),
      ),
    ],
  ),
)

BlocBuilder — widget, който преизгражда UI при всяко ново State. BlocListener — за странични ефекти (еднократна обработка на State без преизграждане на UI): показване на SnackBar, навигация към друг екран. BlocConsumer — комбинация от Builder и Listener за случаи, когато са необходими както преизграждане, така и страничен ефект. BlocSelector — за селективно преизграждане само при промяна на конкретно поле на State.

MultiBlocProvider — widget за вложени BlocProvider без увеличаване на нивото на влагане. Flutter приложение с 10-15 Bloc използва MultiBlocProvider на кореново ниво за регистрация на всички Bloc, достъпни в цялото приложение: AuthenticationBloc, CartBloc, SettingsBloc.

Тестване на BLoC

BLoC се тества изолирано без Flutter widget-и. Достатъчно е да импортирате Dart пакета flutter_test и пакета bloc_test. Тестов сценарий: създайте Bloc, добавете Event, проверете State. blocTest — инструмент, който автоматизира последователността: build → act → expect.

Dart
blocTest<CounterBloc, int>(
  'emits [1] when Increment is added',
  build: () => CounterBloc(),
  act: (bloc) => bloc.add(Increment()),
  expect: () => [1],
)

Mocking: BLoC, който зависи от хранилище или API, се тества с mock-ове чрез mocktail. Хранилището се mock-ва на ниво абстракция, Bloc получава mock-нати зависимости чрез конструктора. Hydrated Bloc — разширение за автоматично запазване/възстановяване на състояние в локално хранилище. Тества се с HydratedBlocStorage и временно файлово хранилище.

BLoC в продукция

Папки и файлове: типична структура на Flutter проект с BLoC: bloc/counter_bloc.dart, bloc/counter_event.dart, bloc/counter_state.dart. За 30+ екрана се препоръчва групиране по функционалност: features/auth/bloc/, features/cart/bloc/. Всеки Bloc — отделен файл, всеки Event и State — или в отделни файлове, или в един файл с Bloc.

Производителност: BLoC не създава допълнително натоварване върху празни Stream. BlocBuilder използва buildWhen за филтриране на преизграждания — widget-ът се актуализира само при промяна на конкретно условие. Close гарантира, че неактивните Bloc не консумират памет. Според Flutter DevTools, BLoC добавя по-малко от 1% към размера на пакета.

Миграция от Provider: BLoC лесно съществува съвместно с Provider в един проект. Поетапна миграция: първо най-сложните Provider се заменят с Bloc, след това останалите. BlocProvider е съвместим с дървото на Provider: старите widget-и могат да използват Provider, новите — BlocProvider, в едно и също приложение.

Често задавани въпроси

Как BLoC се различава от Provider във Flutter?

BLoC използва Event + Stream за изолация на бизнес логика и строга типизация. Provider — обвивка около InheritedWidget за просто инжектиране на зависимости и ChangeNotifier. BLoC е по-подходящ за сложни сценарии с множество състояния, Provider — за локално UI състояние. BLoC изисква повече boilerplate, но предоставя пълна проследимост чрез Event.

Какво е Hydrated Bloc?

Hydrated Bloc — разширение от пакета hydrated_bloc, което автоматично запазва последното State в локално хранилище (по подразбиране Hive). При рестартиране на приложението, Bloc възстановява запазеното състояние вместо началното. Това решава проблема с персистентността без ръчно извикване на запазване: вход, количка, настройки се запазват автоматично между сесиите.

Как да обработваме грешки в BLoC?

Грешка в BLoC се обработва чрез try-catch вътре в mapEventToState или on<Event>. При грешка, Bloc връща State на грешка: yield LoadError(error.message). На UI, BlocListener или BlocConsumer проверява State за типа на грешката и показва SnackBar или диалог. BlocObserver глобално записва всички необработени изключения.

Може ли BLoC да се използва с други рамки?

BLoC е модел, специфичен за Flutter, тъй като използва Dart Stream и Flutter widget-и. Концепцията Event → Bloc → State може да бъде адаптирана за AngularDart и Server-side Dart, но основната екосистема (BlocProvider, BlocBuilder, BlocObserver) е свързана с Flutter. За React Native използвайте Redux или MobX, за SwiftUI — Combine + MVVM.

Какво да изберем: Bloc или Cubit?

Cubit — за прости състояния (брояч, toggle, формуляр с 2-3 полета). Bloc — за сложна логика (новинарски поток, завършване на поръчка, авторизация). Основно правило: ако е необходимо проследяване на всяко действие (Event) за аналитика или отстраняване на грешки — Bloc. Ако са достатъчни методи, които променят състоянието — Cubit. И двата модела съществуват съвместно в един проект.

Обобщение

  • BLoC — модел за управление на състоянието на Flutter чрез Event → Stream → State
  • Event — действие (клик, зареждане), State — реакция (данни, грешка, зареждане)
  • Cubit — опростена версия без Event, до 50% по-малко boilerplate
  • BlocProvider — инжектиране на Bloc в дървото от widget-и с автоматично close
  • BlocObserver — глобален мониторинг на всички Bloc и Cubit в приложението
  • Hydrated Bloc — автоматична персистентност на състоянието чрез Hive
  • blocTest — инструмент за модулно тестване на Bloc с изолация от Flutter

Ще разработим мобилно приложение под ключ

IT Sectr създава iOS и Android приложения за стартъпи и бизнеси от 2017 г. Ще ви консултираме и ще предложим най-доброто решение.

Обсъдете проекта

Прочетете също