Mini: Embrace Reactivity. Flux & Android

Francisco García Sierra
BQ Engineering
Published in
6 min readNov 8, 2018

Flux is an architecture pattern created by Facebook and used to build client-side web application. It complements Reacts view components by utilizing an unidirectional data flow. Flux eschews MVC in favor of a unidirectional data flow.

Across this article we will explain how Flux works, together with how to implement it in our Android applications using an external framework developed for the Android platform using Kotlin thus allowing us to minimize the boilerplate that this architecture could produce in other languages without using popular JS framerworks.

Data Flow : Dispatchers, Stores and Views

The unidirectional data flow is the core idea of the Flux pattern. In order to ensure this flow we will use a series of structures. The Dispatcher, Stores and Views are independent nodes with different inputs and outputs. Actions are just bare objects that carries an optional payload of data.
Let’s see through an example how they work and interact with each other.

When an user interacts with a view, it propagates an Action (use case) that will be handled by a certain number of stores that hold the actual business logic of the application. The state of each of these Stores conforms the state of the application and will be mutated by the dispatch of Actions by means of the Dispatcher. Finally, our views will change reactivity based on the changes of these States.

Let’s see it in more detail.

Flux flow diagram

Dispatcher

The dispatcher is the central hub that manages all data flow in a Flux application. It’s just a mechanism that distributes the actions to the stores. Each Store provides a callback for one or more Actions. When a new action go though the Dispatcher, all the stores receives this action and trigger their callbacks if needed.

Stores

Stores contains the application state and the logic. Their function is to hold and manage the state related to a particular domain within the application. Stores register itself to certain Actions and triggers, a state change together with other side effects when these Actions are dispatched. An action should result in an update to the state of one or multiple stores.

Views

Views on Flux listen reactively the changes emitted by the stores. On the Flux pattern, the changes in the views should be a side effect caused by a certain change in the stores.

Actions

The actions are simple objects dispatched though the Dispatcher to the Stores, containing new data provided to cause a state change. For example, the action LoginAction(email : String, password : String)contains the payload of data needed to make a call to an API REST with a login request.

The Clean pattern

Clean architecture is a pattern for a modular system, which strictly follows a design principle called separation of concerns. This style of architecture focuses on splitting software into different layers, looking forward of simplify the development and make easier the maintenance of the application itself. When layers are well-separated, individual pieces can be reused, as well as developed and updated independently.

The architecture is usually composed of four fundamental layers. These layers will be identified as:

  • Enterprise Logic : Data models and entities.
  • Application Logic : Business logic and use cases.
  • Presentation Logic: Presentation design patterns.
  • Infrastructure Logic: External dependencies.
The Clean Architecture Pyramid, © 2018 PXPGraphics

Also, each layer should respect these rules:

  1. Should be testable.
  2. Should be independent of a user interface.
  3. Should be independent of a database.
  4. Should be independent of interfaces to third-party dependencies.
  5. Should be respectful of boundaries.

Clean Problems

  • Enforce the separation even if you don’t need to share modules with multiple projects can be overhead: as you need layer-specific objects and mapping in between
  • Navigation should be a domain-layer responsibility, but it is a common problem that people abuse Activities and make navigation state implicitly part of the task stack.
  • Hiding certain things under interfaces can be hard, often people still leak details, or their abstraction does not properly handle how their library of choice actually works.
  • Lots of boilerplate

So how is Flux different from Clean?

  • The Flow of the app is essential to Flux and there are very strict rules that are enforced by the Dispatcher. In Clean the flow isn’t enforced and most Clean patterns implement it differently
  • Unidirectional flow: Every change goes through the dispatcher. A store can’t change other stores directly. Same applies for views and other actions. Changes must go through the dispatcher via actions. In Clean it’s very common to have bidirectional flow
  • Stores don’t need to model anything and can store any application related state. In Clean models try to model something, usually single objects

Mini. A Minimal Android Flux Architecture

Mini is a minimal Flux architecture written in Kotlin that also adds a set of useful features to build UIs fast.

The objective of this framework is to develop a reactive application with good performance (using code-gen over reflection). Feature development using Mini is fast compared to traditional architectures (like CLEAN or MVP), low boilerplate and state based models make feature integration and bugfixing easy as well as removing several kind of issues like concurrency or view consistency across screens.

Sample case

Let’s pose a typical case for a backend related application. We want to do a login request to our backend. If this request success, the user will be redirected to the home screen, if it fails, an error will be shown.
For this we will just need to build:

  • An Action as an use case for our login request and the result callback.
  • A Store and that contains the application state regarding the session.
  • A View subscription to SessionStore state changes. This can be made listening all the changes for mapping data or custom logic or a single one for navigation purposes.

With this code, the flow will happen in the next way:

  • After click on the button login() is called and LoginAction is dispatched.
  • The Reducer functions that receives LoginAction are executed.
  • The state will change the value of loginTask to RUNNING in the state and the Controller makes the async operation over the backend. When the async operation will end LoginCompleteAction will be dispatched.
  • The state will change the value of loginTask to SUCCESS or FAILURE depending of the data retrieved.
  • The view will navigate to home or show an error depending of the state.

Testing

Mini includes an extra library called mini-android-testing with a few methods and Expresso TestRules to simplify your UI tests over this architecture.

  • TestDispatcherRule : This rule will intercept any action that arrives to the Dispatcher, avoiding any call to the Store and their controllers. If we include this rule we will need to change the states manually in our tests.
  • CleanStateRule : It just reset the state of your stores before and after each test.

Test that actions are correctly dispatched:

View — Store Test

Test that a view correctly changes based on an specify state:

State — View Test

Mini on Github

You can grab Mini by adding dependency to your build.gradle file:

implementation 'com.github.pabloogc:Mini:1.0.7'
kapt 'com.github.pabloogc.Mini:mini-processor:1.0.7'
androidTestImplementation 'com.github.pabloogc.Mini:mini-android-testing:1.0.7' //Optional

These are just a few examples of how to use the library, feel free to use it, open issues, creating pull requests and contribute to the project.

Join us on Github! Happy coding!

Links and resources

--

--