An overview of reactive programming with Android

The Android platform is asynchronous by nature. And so are android apps. Information is flowing asynchronously through your app, from multiple sources. The system will trigger your broadcast receivers, forward intents, and recreate your UI on each configuration change. The user will keep interacting with the UI, and network requests may respond (or eventually fail) at any moment.

Tackling such issues in an imperative programming way will make you write code to coordinate and handle all these interruptions while maintaining a consistent state. If you build android apps, chances are you’re suffering from listeners, callbacks, threads and state management. And when I say suffering I really mean it:

fundoTheThing(args: Any) {
    fooRepository.doA(
        args,
        object: ApiCallback() {
            fun onSuccess(fooResult: Any) {
                barRepository.doB(
                    fooResult,
                    object: ApiCallback() {
                        fun onSuccess(barResult: Any) {
                            showData(barResult)
                        }
                        fun onError(error: Throwable) {
                          ...
                        }
                    }
                )
            }
            fun onError(error: Throwable) {
                ...
            }
        }
    )
}

What’s Android reactive programming?

Few years ago, Google introduced Architecture Components, especially view model and live data. You are probably already using these components, and if not then you should. Anyway, in a nutshell, a view model helps you survive activities and fragments lifecycles, and live data will make your UI spontaneously react to data change. In fact, live data follows -in a primitive way- a reactive programming paradigm.

Reactive programming is a paradigm in which data change propagates through data streams. Building an app will mainly consist of wiring these data streams using what we call “operators”. The real power of such operators is the ability to alter the data. For instance, you can filter, map, merge, split, flatten or chain your data streams, this is even the way you will code your business rules in a reactive app. Plus, it’s usually very readable.

How-to: code sample

Let’s suppose you are building a Twitter-like app and are about to code the follow button in profile details screen.

Since every user interaction is seen as a “UI event”, the follow button will just fire a ProfileUiEvent.Follow and let the magic happen.

Let’s go through a step-by-step implementation

In ProfileActivity we bind clicks on follow button with the view model main entry (each button click will fire a ProfileUiEvent.Follow)

import com.jakewharton.rxbinding2.view.clicks
...
val followClicksStream = follow_button.clicks().map { ProfileUiEvent.Follow }
viewModel.bind(followClicksStream)
...

Thus, all button clicks will go through the view model main entry (eventsStream).

Takeaways

Code sample

Do I need all of that?

Clearly, there are a lot of notions to get familiar with before starting to build reactive android apps. That’s one of the main reasons developers and companies just give up doing so. It’s actually an effective cost to deal with when you consider building a reactive app. But, is it really worth it?

It’s a long-standing debate inside the Android engineering team here @ Fabernovel. We usually list pros & cons for each new project before making such decision. If the app we’re about to build depends on data that changes very frequently and from different sources, we tend to prefer a reactive architecture, otherwise, we see it more like an unnecessary over-engineering. Here’s a list of main pros & cons of reactive programming compared to imperative programming.

Pros

Cons

As an alternative, one can consider building a coroutine-based architecture. Lately, we started using coroutines in production @ Fabernovel, substituting RxJava, and the feedback is quite positive. Stay tuned for an overview of a coroutine-based architecture…

By then, happy coding :-)