Kotlin + Jetpack + Flux

My winner team for simple unidirectional data flow

Julien Piatek
4 min readFeb 3, 2019

I’ve tried a lot of different software architectures through my Android dev career, from God Activity to MV[insert your favorite letters], which can be a pretty nice choice depending on what you are trying to do.

Recently, I had the chance to join a team doing something totally different, using a cocktail made of Kotlin + RxJava + Flux. Until that point, I was using Rx only for asynchronous API calls, and I never tried the Flux architecture, so I let you imagine my face the first time I checked the codebase.

What is Flux ?

Ok, you guessed it, Flux is a software architecture, a way of building applications some people at Facebook thought about some years ago. It was first mainly used for web apps development, but recently is gaining popularity among mobile app developers.

I won’t dig too deep into the details, but the three reasons why I enjoy coding with this architecture are :

  • Separation of Concern is strong in this one. Every class has only one role, and data flows only in one way, which is easy to understand.
  • It is very easy to test.
  • In combination with Kotlin sealed classes and generics, we can leverage the power of types to make the development process safer, and in my opinion more enjoyable.
  • [Bonus] Beauty. The first time I learnt about Flux, I really thought the data flow has some similarities with a living creature anatomy.

There is a lot of different ways to implement Flux. In my solution, I chose to make each screens totally independent. So here is the classes you need to create for each screens:

  • State: This class should represents your screen. It contains data needed to (re-)create everything the user can see and interact with. It should be observable, so the view can automatically react to any changes. Jetpack LiveData is the best candidate to achieve that easily.
  • View: It can be an Activity or a Fragment, it will observes and react to any change in your State to update the view. The view should not contain any other things except view binding and rendering logic.
  • Action: The only way to update your state is through Actions. Each action will affect the state in a different way, and it has to be deterministic. For example, user interactions (button tap, etc.), network request, response handling, etc. All of these should be distinct actions.
  • Reducer: This is where the business logic of our app happens. The reducer will make new states, with the current state and an action as only ingredients.
  • Store: The store is a big wrapper, containing our reducer and the app states. Which lead us to the big picture:
This looks like a living being anatomy, right? ……..

Why Kotlin is in the recipe ?

Java is fine to implement what I just shown you, but Kotlin will makes your life easier.

Sealed classes + when

Your reducer should handle the logic for every possible Actions. To make sure you will never forget to handle any action, you should use sealed classes in combination with the when operator. Indeed, the when operator won’t let you compile if you forget to handle a certain action type, which is a nice safety.

Generics

Another safety. In this architecture, I want to emphasis that I want one store per screen. Each screen should have its own set of [Store, Reducer, Actions, State, View]. To make sure you will never try to make a reducer with the wrong set of actions and states, it is wise to use generics. By doing that, your IDE won’t let you compile if you try to create a reducer with another screen’s state or reducer.

Sample application

I made a very simple sample app to illustrate all the concepts in this post. Please don’t hesitate to check it, and give feedback or help me improve it :)

--

--

Julien Piatek

Passionated about tech and the future we can build with it.