Library / SDK
felangel/bloc avatar
felangel/bloc

felangel/bloc: a Dart state management library built around events and states

A predictable state management library that helps implement the BLoC design pattern

12,483 stars3,420 forksDartMIT

At a glance

What is it?
The bloc monorepo splits the BLoC pattern into nine pub packages, from the core bloc library to flutter_bloc, hydrated_bloc and bloc_test. Here is who it fits, how a counter is wired up, and where the approach costs you.
Who is it for?
Adopt felangel/bloc if your team already thinks in events and immutable states, or if you want the same pattern to work in flutter_bloc, angular_bloc and plain Dart. Do not adopt it if the app is a handful of screens with local state, because the event and state classes will outnumber the widgets they serve.
Can I use it commercially?
Yes. MIT is a permissive licence: you can use, modify and sell software built on it, as long as you keep its copyright and licence notices.
Is it still maintained?
Yes. The repository last received commits 5 days ago.
What is it written in?
Mainly Dart, according to GitHub's language statistics.

Answers come from the project's GitHub data, last synced on September 29, 2026, and from our analysis. They are not legal advice.

DEEP OPEN-SOURCE ANALYSIS

The problem felangel/bloc solves: presentation code that knows too much

The README states the goal plainly: to make it easy to separate presentation from business logic, facilitating testability and reusability. That is the whole pitch. In practice, a Flutter widget that calls an HTTP client, parses a response, decides whether to show a spinner and stores the result in a field has five reasons to change. The BLoC pattern moves the decision-making out of the widget and leaves the widget with one job: render whatever state it is handed.

The target reader is a Dart or Flutter developer on a codebase where the same business rule is implemented twice, once in a screen and once in a background refresh path. The repository is organised as a monorepo with nine packages under packages/, plus examples/ directories such as flutter_todos, flutter_login, flutter_infinite_list and github_search. That layout tells you the intended scope: not one library, but a family. bloc is the core, flutter_bloc is the Flutter binding, angular_bloc is the AngularDart binding, and bloc_test, hydrated_bloc, replay_bloc, bloc_concurrency, bloc_lint and bloc_tools cover testing, persistence, replay, event concurrency, linting and tooling respectively.

Events in, states out: the mechanism behind bloc and flutter_bloc

A bloc is a Dart object with two type parameters, one for the events it accepts and one for the states it emits. You add an event; the bloc maps that event to zero or more states through registered handlers. The widget layer subscribes to the state stream and rebuilds. Nothing in the widget decides what the new state should be, which is the separation the README describes.

The companion packages change one axis each. hydrated_bloc persists and restores bloc state through a storage backend, so an app restart does not reset it. replay_bloc keeps previous states available for replay. bloc_concurrency supplies alternative event transformers, which is how you choose whether events are processed concurrently, sequentially, or with the newest one dropping the rest. bloc_test provides a blocTest helper so a bloc can be driven through a sequence of events and checked against expected states without a widget tree. bloc_lint adds lint rules for the pattern, and bloc_tools is the tooling package, currently at 0.1.0-dev.24, so treat it as pre-release.

The cost of this structure is visible in the repository itself: examples/flutter_counter exists because even a counter needs a state class, an event class and a bloc. That is the trade you are making. You buy a testable seam and pay in boilerplate.

Installing felangel/bloc and writing a first bloc

Everything ships on pub.dev, so installation means adding the package you need and resolving it. The README lists each package with a link to its own pub page rather than giving a single install command, so what you add depends on your target: bloc for plain Dart, flutter_bloc for Flutter, angular_bloc for AngularDart. The README does not print a pubspec.yaml snippet or a pub add command, so the concrete next step is to open the pub page for the package you chose and follow the install instructions there.

The next step is the bloc itself. The README points readers at the flutter_counter tutorial on bloclibrary.dev rather than inlining the code, and the repository ships the matching example under examples/flutter_counter, so that directory is the reference to read alongside the tutorial. The README also links a dedicated Flutter Bloc package README for the details.

The wiring in the widget tree is the part people get wrong first. A bloc has to be provided above the widgets that read it, and the reading widget rebuilds when the state changes. If you provide the bloc below the widget that consumes it, or create a new instance inside build, you will see state resets that look like a logic bug but are a tree-placement mistake. The repository's examples/ directory holds working versions of this for counters, todos, login, infinite lists and forms.

Where felangel/bloc is the wrong tool

The pattern assumes your application state has meaningful transitions worth naming. A settings screen with three toggles does not. If you model each toggle as an event and a state class, you have written more Dart than the feature contains, and reviewers will start asking why. The repository's own examples are chosen accordingly: flutter_todos, flutter_infinite_list, flutter_weather, flutter_firebase_login. These are features with loading, success and failure paths. That is the shape the library rewards.

The second boundary is concurrency. A bloc processes events, and the default behaviour is not something the README explains on the front page. bloc_concurrency exists precisely because event ordering is a real decision that the core package does not make for you. If your feature fires rapid user input, you need to pick a transformer deliberately, and the documentation for that lives in the bloc_concurrency package README, not the top-level one.

The third is the learning curve for a team. The README does not document rollback, and the migration guide is a separate page at bloclibrary.dev/migration, which means upgrading across major versions is a reading task, not a mechanical one. Anyone expecting a codemod should check that page before planning the upgrade.

Bloc compared with Riverpod and provider

Riverpod and provider solve dependency access and state exposure; bloc solves state transition. The difference in approach is where the logic lives. With provider, a ChangeNotifier holds mutable fields and calls notifyListeners, and the widget reads those fields directly. With Riverpod, a provider exposes a value and widgets watch it, with the recomputation rules expressed in the provider graph. In both, the state is whatever the object currently holds.

With bloc, the state is a value you construct and emit, and the only way to change it is to add an event that a handler responds to. That gives you a log of transitions for free, which is why bloc_test can assert on a sequence of states and why replay_bloc is a small package rather than a rewrite. It also means every transition is named, which is either the best part of the library or the most annoying, depending on the feature.

The honest comparison is cost per feature. For a screen with one async fetch and one list, provider or Riverpod will be shorter. For a flow with retries, cancellation, optimistic updates and a test suite that asserts on intermediate states, bloc's event log pays for itself. The two are not exclusive either, since bloc is a plain Dart library and can sit under a Riverpod-managed dependency graph.

Maintenance, releases and the MIT licence

The repository is not archived, and the last push was on 2026-09-18, so the project is being worked on now. Releases are per package rather than a single version number, which matters when you plan an upgrade. Recent tags include bloc-v9.2.1 on 2026-05-12, bloc_lint-v0.4.2 on 2026-07-04, and bloc_tools-v0.1.0-dev.24 on 2026-04-24. The dev suffix on bloc_tools means that package is not stable, and depending on it in production code is a choice you should make knowingly.

The practical upgrade cost is that bloc, flutter_bloc, hydrated_bloc and bloc_test move on their own schedules. Adding flutter_bloc will not pull a new major of bloc for you, and a mismatch between the core and the Flutter binding is the most common source of confusing errors after an upgrade. Pin the packages you use and read the migration guide when a major lands.

The licence is MIT, stated in the repository's LICENSE file and in the README badge. MIT permits commercial and closed-source use with attribution and without copyleft obligations on your own code. That is a summary of the licence text, not legal advice; if your organisation has a policy on third-party dependencies, run it through that process.

Editorial conclusion

Adopt felangel/bloc if your team already thinks in events and immutable states, or if you want the same pattern to work in flutter_bloc, angular_bloc and plain Dart. Do not adopt it if the app is a handful of screens with local state, because the event and state classes will outnumber the widgets they serve. Before committing, read the migration guide at bloclibrary.dev/migration and check the changelogs for the packages you actually import, since bloc, flutter_bloc and hydrated_bloc version independently.

Frequently asked questions

What does BLoC stand for in Flutter?

BLoC stands for Business Logic Component, and felangel/bloc describes itself as a library that helps implement the BLoC design pattern. The README frames the goal as separating presentation from business logic to make both testable and reusable.

Which provider is better for state management, Riverpod or BLoC?

The README does not rank them. The difference visible in felangel/bloc is that state changes are driven by events mapped to emitted states, while Riverpod-style providers expose a value that widgets watch. Which fits depends on whether your feature has named transitions worth testing.

Which is better, BLoC or provider?

felangel/bloc does not compare itself to provider. With bloc, the only way to change state is to add an event a handler responds to, which makes a sequence of states assertable through bloc_test. That structure costs more code per feature than a mutable notifier.

Which state management is best for Flutter?

The repository does not make that claim. It ships nine packages, including flutter_bloc for Flutter, angular_bloc for AngularDart and the core bloc package for plain Dart, and points to bloclibrary.dev for the documentation.

Official sources

  1. felangel/bloc on GitHub
  2. License: MIT
  3. Project website
  4. README
  5. Releases
For maintainers

Add this badge to your README

If you maintain this project, the badge below links readers to this analysis and shows its maintenance status from the daily GitHub snapshot. Paste the markdown into your README; add ?metric=license or ?metric=stars to the image URL for a different field.

Add this badge to your README

markdown
[![Hysen Labs](https://hysenlabs.com/badge/felangel-bloc.svg)](https://hysenlabs.com/projects/felangel-bloc)
Community notes

Community notes