bloc_logic 0.1.5
bloc_logic: ^0.1.5 copied to clipboard

Flutter Android iOS

Bloc Logic plugin.

Bloc logic #

I really like using bloc pattern for state management. In my opinion, it's the best decision for most tasks. This pattern use streams and it's not bit convenient. But we have plugin flutter_bloc by Felix Angelov. That plugin is easy for understanding and required less strings of the code. Thats why most of developer prefer to use that plugin. However, when it is created a big project with large amount logic operations, that advantages are disappeared. We describe the same events, states and blocs again and again. Most of that blocs have the same behavior and use the similar logic. I has noticed that and grouped blocs' behavior. As it turned out, their amount is not too big. And we can use these behaviors to create large logic constructions. We can use blocs' behaviors like bricks to building our projects.

Clean code #

This pattern can to use for creating clean code architecture. In the most examples for bloc it shown only two layers: user interface and data layer. Bloc is between these two layers. It connects them. But it only controls state and doesn't contains any logic. In my opinion, we must inject logic layer between bloc and data layer. It will allow us put out of brackets bloc. We won't need to change bloc anymore. All changes we will make only in the logic layer. I called them use cases.

In totally, we have next layers:

  • user interface
  • bloc
  • use cases
  • data (repository and datasource)


Use cases #

All use cases have the same functionality. In the total case it send some value and get some result. That result can be two types: success and failure. When the result is a success, it get some successful value. When the result is a failure, it get some failure value. For example it can be a error string. So, every use case defined by three parameters:

  • S - success
  • V - value
  • F - failure

You can use for our use case next class with those parameters:

IUseCase<S, V, F>

You must replace generics S, V, F with types for our task. For example:

class ExampleUseCase implements IUseCase<List<String>, int, String>

What does it mean? You create new use case. When you send to it integer value, it can return strings list, if it is success, or error string if it a failure.

There are only two types of the use cases: synchronous and asynchronous. The synchronous use case run momently. But asynchronous use case requires a some time. For example, if you send request to server, the answer will return for several milliseconds. If you want to use asynchronous use case, take class IFutureUseCase like simple IUseCase.

class ExampleFutureUseCase implements IFutureUseCase<List<String>, int, String>

Result #

As I’ve already said use cases return the results. These results can be two types: success and failure. Success result returns dynamic type payload. It can be any variable what you want to get from use case. For example it can be the clients list. Failure result also can return any types variable. In most cases I use simple String type. I return error string and it enough for most tasks. You can use more difficult class failure which contains of not only error string but error code.

Logic Patterns #

Most of blocs behaviors are the same ones. We are repeating them again and again. I have highlighted some of them and have created special classes for convinient to use these patterns. Its are called blocs logics. Some of them I expose for you below:

Check Logic #

It is the very simple logic. This pattern does only turning on or off some switcher. For example we can see it when use Checkbox widget. It can seem that it is unnecessary action. But it's not right. In the future you can use this logic together with many different logics for building stonge app architecture.


For beginning you must initialize and define disposing our logic. We must do it in the our StatefulWidget.

  CheckLogic _checkLogic;

  void initState() {
    _checkLogic = CheckLogic();

  void dispose() {

Lets add button which has only two states - turning on and turning off. This button is wrapped in CheckLogic, which has module child. Button widget redraw every times when logic is switched. The logic changes with helping turnOn() and turnOff() methods.

  child: () {
    return RaisedButton(
      child: Text(_checkLogic.isTurnedOn ? 'Turn on' : 'Turn off'),
      color: _checkLogic.isTurnedOn ? Colors.deepOrange :,
      textColor: Colors.white,
      onPressed: () {
        if (_checkLogic.isTurnedOn)

Radio Logic #

The next simple pattern is RadioLogic. You can build and control radio buttons with it for example. If you want to add tabs in your app RadioLogic is the best way for it.


How in the first case there is not any usecases. It is unnecessary. To start we initialize logic and dispose it:

  RadioLogic _radioLogic;

  void initState() {
    _radioLogic = RadioLogic();
  void dispose() {

For example we want create several buttons which will we work like radio buttons and will change color if it selected. We must wrap every button with builder of radio logic. In practice we do it only one time. If we want to select current button we use procedure select with integer index parameter. This parameter means current index in the items list.

return _radioLogic.builder(child: (currentIndex) {
  return Center(
    child: RaisedButton(
      child: Text(list.elementAt(index)),
      color: currentIndex == index
          ? Colors.deepOrange
          : null,
      onPressed: () {;

Valid Logic #

Next pattern consist also use case. It allows to add logic in this file and don't touch bloc files. We have next task. We must input string value in the text field and check it. The length of this string must more then zero and less four. If value has error it must appear below text field.


In the beginning declare private ValidLogic object. And also add dispose procedure to clear this logic from the memory. Don't initialize this logic. We will initialize one a bit later. Also declare private TextFieldController and dispose it again.

  ValidLogic _validLogic;
  TextEditingController _validController;

  void dispose() {

After that we need create new file with name valid_use_case.dart and fill in this file next code:

class ValidUseCase implements IUseCase<String, String, String> {
  Result<String, String> execute([String value]) {
    try {
      if (value == null) return Result(success: '');
      if (value.isEmpty) return Result(failure: 'The value must not be empty.');
      if (value.length > 3)
        return Result(failure: 'The value must be less then 4.');
      return Result(success: value);
    } catch (e, stacktrace) {
      print('BLOC_LOGIC: ${e.toString()} STACKTRACE: ${stacktrace.toString()}');
      return Result(failure: e.toString());

New class is implemented from IUseCase class. It is very important to understand with types parameters of use case. There three parameters in the IUseCase. All of them are String.

IUseCase<S, V, F>    ---->    IUseCase<String, String, String>

It means the next:

  • S - success - this is success result type. We want to get String value in success case.
  • V - value - this is value parameter type. We send it to the procedure. This type is String again.
  • F - failure - this is failure type. Usual it is String type. But it can be a class wich can contains not only string message but error code.

And now we can initialize our ValidLogic. We can notice that use case was added into our logic.

  void initState() {
    _validLogic = ValidLogic(usecase: ValidUseCase());
    _validController = TextEditingController();

And in the end we build widgets and use ValidBloc Builder for it. Procedure Builder takes state which contains success or failure result. If this result has failure error message appears below text field.

  _validLogic.builder(valid: (state) {
    return TextField(
      controller: _validController,
      decoration: InputDecoration(
            state.result.hasFailure() ? state.result.failure : null,
      onChanged: (value) {
pub points

Bloc Logic plugin.



API reference





bloc, flutter, flutter_bloc, meta


Packages that depend on bloc_logic