What you’ll find in this article:

Introduction

Reactive Programming and Streams

Observer Pattern

BLoC

Implementing BLoC

MobX

Implementing MobX

Honorable mentions

Comparing approaches

My personal choice

Introduction

In this article, we are going to talk about MobX library and BLoC pattern with the objective to understand these two names that are at the community mouth.

Before we enter in these subjects, we need to know about reactive programming and observer pattern

Reactive Programming and Streams

Streams are continuous flows of data. It is a very elegant name for something that has a very simple operation. It is a sequence of data, with input and output.

Reactive programming is a paradigm based on data flow and its propagation through the application and it has three main characteristics:

Responsive Resilient Elastic

Responsiveness comes from the timely response. With it we gain the ability to do computational operations in less time and using few resources. In addition, reactive programming avoids creating threads for costly tasks when there is no need, eliminating the consume of resources to keep threads idle.

Resilience comes from the facility to work around failures and deal with errors that may happen, keeping the application running. For example, if you have a Stream that receives the data returned by a function and an error occurs in this function, you will be able to handle this error very easily and your application will continue to work normally, as the Streams are independent of each other.

The elasticity comes from the ability to react well under high demand, a reactive system knows how to vary the use of its resources depending on the amount of load put on it, knowing when to create a new thread or to close a thread that is unused.

Observer Pattern

Defines the “one-to-many” dependency between objects, where when an object changes, it notifies all other dependents.

BLoC

The BLoC (Business Logic Component) is a design pattern that emerged with the intention of promoting the reuse of code and the sharing of the same business logic between different platforms, such as web, mobile or backend.

Currently, it aims to make the code of your Flutter application more maintainable and testable from a separation between the business logic and the user interface.

BLoC design guideline by Paolo Soares at Dart Conf

BLoC Core Concepts

StreamController

StreamController, is used to control all of your data flow, through it you will control: the input and output of data; checking and handling errors; closing the transmission of this data.

So we are going to declare an integer to keep the current value of the counter in order to transmit it through our Stream.

import "dart:async"; class CounterBloc {

int _counter = 0; final _controller = StreamController();

}

Stream

Stream will be theoutput of data and normally we access it by a getter.

Sink

The only term that is not very suggestive, but Sink will be the data input.

class CounterBloc {

int _counter = 0;



final _controller = StreamController(); Stream get output => _controller.stream;

Sink get input => _controller.sink;

}

Incrementing the counter

increment() {

input.add(_counter++);

}

Closing the StreamController

dispose() {

_controller.close();

}

StreamBuilder

It is a component that receives a data stream and updates itself when there is a new data entry, the current value of the stream is called a “snapshot” which is a capture of the current data of the data flow(stream).

StreamBuilder(

stream: _counterBloc.ouput,

initialData: 0,

builder: (context, snapshot) {

return Text(‘$snapshot.data’);

},

),

MobX

Distinct of BLoC which is a design pattern and whose implementation is open to the developer, MobX is a Transparent Functional Reactive Programming(TFRP) state management library that implements the observer pattern with a friendly syntax and simple core API that makes learning easier when you’re a beginner. MobX is scalable and has been used in countless large projects like Microsoft Office, Battlefield 1, Jenkins, Coinbase.

MobX Core Concepts

Observables: Represent the reactive data, can be any object.

final name = Observable(‘Flutterando’); final object = Observable(

Community(

nome: ‘Flutterando’,

members: 5000,

),

);

Cool but it is very boilerplate, right?!

Don’t worry, the code generation will save our precious time.

You can through build_runner generate all this boilerplate code using only annotations.

@observable

String name = ‘Flutterando’; @observable

Comunidade object = Community(nome: ‘Flutterando’, members: 5000);

Computed Values: It is data that is derived from the observables, very useful for validations.

@observable

String name; @observable

String email; @computed

bool get canSend => name != null && email != null;

Well, the data of MobX will be composed of observables and computed values.

Actions: It is the responsible for mutate the data(observables).

final name = Observable(‘Flutterando 4k members’); final updateMembers = Action(() {

name = ‘Flutterando 5k members’;

}); With codegen: @observable

String name = ‘Flutterando 4k members’; @action

void updateMembers() => name = ‘Flutterando 5k members’;

Reactions: As said, the reactions are the MobX magic, it will react to our data changes and notify the observers, that will re-build the widgets with updated data.

There’s four types of reactions, they all return a disposer that is similar to Stream.close().

Always dispose the reactions!

The reaction autorun, as the name says, it will run when declared and re-run in every changes of the data that is inside your fn.

String name = Observable(‘Flutterando 5k members’); final dispose = autorun((_) => print(name.value)); name.value = ‘Flutterando 5k and hundred members’; dispose(); // fechando a reação // Output:

// Flutterando 5k members

// Flutterando 5k and hundred members

The type reaction will be similar to autorun but won’t fire on declaration.

String name = Observable(‘Flutterando 5k members’); final dispose = reaction((_) => name, (name) => print(name)); name.value = ‘Flutterando 5k and hundred members’; dispose(); // Output:

// Flutterando 5k and hundred members

The when reaction will triggers based on a condition and after triggered it auto-disposes.

String name = Observable(‘Flutterando 5k members’); final dispose = when(

(_) => name.value == ‘Flutterando 5k and hundred members’,

() => print(‘members was updated’),

); name.value = ‘Flutterando 5k and hundred members’; dispose(); // Output:

// members was updated

The last one, asyncWhen that is the asynchronous version of when.

final name = Observable(‘Flutterando 5k members’’); void waitForCompletion() async {

await asyncWhen(() => name.value == ‘Flutterando 5k and hundred members’); print(‘name was updated’);

}

Observers(Widget): now using flutter_mobx, which is a package of widgets to consume MobX in the UI.

It is a widget that listen to the observables, when observable changes the reactions notifies the Observer.

Honorable mentions

RXDart

RxDart adds additional capabilities to Dart Streams and StreamControllers. Dart comes with a very decent Streams API out-of-the-box; rather than attempting to provide an alternative to this API, RxDart adds functionality from the reactive extensions specification on top of it. RxDart does not provide its own Observable class as a replacement for Dart Streams. Rather, it provides a number of additional Stream classes, operators (extension methods on the Stream class), and Subjects.

flutter_bloc

A dart package that helps implement the BLoC pattern.

Comparing these two approaches

Business Logic Code

UI Code

Pros and Cons

My personal choice

So, I used BLoC along one year, implementing with RXDart, flutter_bloc and it solved all my problems but I also lost a lot of time learning reactive programming, writing boilerplate code, trying to teach newcomers on my project, switching between implementations.

So today I prefer the simplicity of MobX which I can write faster, teach easily, maintain a standard code.

In other words, I chose keep it simple.

Thanks

What is the approach that you use or is going to use?

My contact: LinkedIN, GitHub, Twitter.