It's so simple that it may not answer many questions you have about blocs. The above example is the most simple possible Flutter / Bloc example I can think of. It is considered wrong if you have to use complex boolean clauses like if (bloc.buttonIsDestructive & bloc.buttonIsEnabled & erIsAdmin) For example, in Flutter, it's acceptable to write color: bloc.isDestructive ? Colors.red : Colors.blue. You should limit yourself to a single boolean stream in the bloc. Any branching should be based on simple bloc boolean logic. For example, if you have a number that needs to be converted into displayable currency, that should be done in the bloc. Outputs should be passed to widgets ready to use.
Components should send inputs as is, because there shouldn't be business logic in the widget! If you need to format text or serialize a model, it should be done in the bloc. For example, in a Todo List app, you might have a bloc for the 'Todo List' page, and a bloc for the "Add Todo" page. In reality, the point is that each logical state subject has its own bloc. In general, blocs and top-level Flutter pages have a one-to-one (1:1) relationship. Do whatever else you want, so long as you follow these rules. If you find yourself in a bloc writing if (device = browser)., then you need to reconsider. If you're importing any Flutter libraries into the bloc, then that's UI work, not business logic, and those should be moved into the UI.
Blocs app vs code#
Inputs and outputs are sinks and streams only! No functions, no constants, no variables! (Although, you'll see that this rule is "broken" quite often to make code more concise. These rules were described in the original talk at DartConf 2018 and live in two categories: application design and UI rules.
Those are broad ideas, of course, but they're made clearer by the following non-negotiable rules. This means you can use the same blocs for Flutter, AngularDart, on the server, etc.