Getting Groovy With Reactive Android

“Slow,” a word no one ever wants to see associated with their app. Delay and lag of as little as 100–200 milliseconds will be perceived by users as poor, slow performance. Keeping long running tasks on the main thread will result in that perception, the dreaded “Application Not Responding” (ANR) and a bad user experience. This leaves us developers one choice: concurrent execution of code. The recent growth in popularity of functional programming is well deserved. As things become more asynchronous, the functional model really fits well. Being able to sequence, chain and transform asynchronous operations can be considered a must. However, the mechanisms for asynchronous programming provided in Android leave much to be desired, especially when compared to the web development realm. Many of the ideas and techniques from “enterprise” Java frameworks have not yet migrated to the Android world. Practices that some would consider table stakes for web development on the JVM have just begun to trickle in on Android; dependency management and a modern build system, for example. We can even dream of one day receiving proper support for unit tests.

Continuous Evolution: A Challenge

Every year, Google announces a new version of Android with many new features and APIs. Writing an application that needs to be continuously improved and kept up to date in this ever-changing landscape can become difficult, especially without the basics mentioned above. How do we keep up with new additions and UI paradigms when we have a large code base, ongoing feature development and maintenance? How do we make portions of our app reusable so that as we write new ones we don’t have to keep repeating ourselves?

Fortunately, we can take advantage of the fact that Java isn’t the only JVM language out there, and Android has been gaining popularity and support with some of the other languages. We can also learn from mature Java frameworks and avoid limiting ourselves with the current constraints that we face as Android developers.

Our Path Forward: Being Reactive

At The New York Times, we have been busy trying to answer these questions. We are undertaking a greenfield rebuild of our core Android app. This gives us the opportunity to reimagine the app from the ground up and to tailor the experience to the next version of Android, L. The emphasis will be on reactive functional programming using RxJava and Groovy in order to gain power and expressiveness with very few lines of code while still supporting forward compatibility with Java 8. We will leverage Dagger for dependency injection without runtime overhead and make our code modular and loosely coupled, another tenet of reactive programming. OkHttp will bring SPDY support, letting us use its inherent efficiency and generate concise networking code. I won’t spend the rest of this post diving into each of these technologies, but will instead be discussing how to use them all together.

The Results: Beautiful

App developers frequently rely on a web service to download content. The payload is usually JSON, which then gets parsed; the model objects are populated and then displayed to the user. If any errors are encountered, the user is informed.

Consider the following example:

     networkManager.getData(source)
    .flatMap({ new FeedParser().getMovies(it) })
    .observeOn(AndroidSchedulers.mainThread())
    .subscribe({ Movies m ->
        movies.clear();
        movies.addAll(m.movies);
        notifyDataSetChanged();
    }, { Throwable e ->
            Toast.makeText(context,"Download failed: " +  e.getMessage(),Toast.LENGTH_SHORT)
            .show();
    }, {
        Log.d(this.getClass().getName(), "complete happened");
    });
networkManager.getData(source)

NetworkManager is responsible for downloading the content of a given URL and returning the response body as a string. The getData method is shown below:

public Observable <String> getData(final String url) {
        return Async.start({ getContent(url) }, Schedulers.io());
    }
    private String getContent(String urlString) throws IOException {
        Request request = new Request.Builder()
                .url(urlString)
                .build();
        Response response = client.newCall(request).execute();
        return response.body().string();
    }
Async.start({ getContent(url) }, Schedulers.io());

Async is part of the rxjava-async module and will execute the function passed to it asynchronously. Async.start returns an Observable which emits the value returned by the function passed in to any subsequent Subscriber(s). The client in the getContent method is an OkHttpClient instance and illustrates the ease with which a URL can be downloaded. Transparent gzip, connection pooling and response caching are few other benefits of using OkHttp. The second parameter is the scheduler on which the operation will happen. If it is not passed in, the default is Schedulers.computation() which gets used for computational work like callback processing and should not be used for I/O. Schedulers.io is meant for I/O-bound work, performing I/O blocking asynchronously.

Java 7 does not have lambdas, and yet we are passing in getContent(url) as a parameter. This is where Groovy, with its recently announced Android support, comes in. In the absence of lambdas/closures, we need to take the time and effort to add the anonymous inner class:

Func0 func = new Func0<string>() {
       @Override
       public String call() {
        return "my content";
       }
};
Async.start(func);

With Groovy :

Async.start({ return “my content” })

But wait, Android does not officially support Groovy and Java 8 support will undoubtedly show up eventually. Wouldn’t one want to use Java 8 then? Won’t we have to rewrite everything?

Fortunately, this is not a problem — Groovy has it covered. Converting a closure to a Java 8 lambda is easy, too:

Async.start({ getContent(url) },Schedulers.io())

becomes

Async.start(()->getContent(url),Schedulers.io());

We annotate the .groovy files with @CompileStatic to get performance comparable to that of plain Java. Despite that, we’re still writing Java code wherever possible and only using Groovy with closures. The gradle plugin takes care of compiling both the Java and the Groovy files. In our testing so far, we have not seen any perceivable differences in performance between the Java and Groovy versions of the same app. Still, for those who are really concerned, RetroLambda is an alternative worth considering.

Let’s go back to the code. The next line is:

.flatMap({ new FeedParser().getMovies(it) })

flatMap is a transform operator and will transform the items emitted by an Observable into Observables, then flatten this into a single Observable. The getMovies method is detailed below.

public Observable getMovies(final String json) {
    return Async.start({parseJson(json)}, Schedulers.computation());
}

Since getMovies returns an Observable, flatMap allows us to flatten it and use the value. If an Observable was not returned by getMovies, we could have just used map instead of flatMap.

.observeOn(AndroidSchedulers.mainThread())

observeOn is an Observable utility operator specifying which Scheduler the Subscriber should observe the Observable on — basically, where I want my results delivered. In our case, we use AndroidSchedulers.mainThread to perform actions on the main Android UI thread. AndroidScheduler is available as a part of rxjava-android (Android specific binding for Rx).

.subscribe({..},{..},{..})

This is one of the subscribe variations which takes in three actions (handlers) corresponding to onNext, onError and onComplete notifications. onNext accepts successful emissions from the Observable, in this case Movie objects, made from parsing the feed.

onError handles error notifications. Here, that means any error that might have been encountered during downloading and parsing. This is immensely powerful since both of those actions happened in the background and yet propagated on the main thread.

Since we are using Async.start, onComplete gets fired right after the emission. This means that Async.start is returning an Observable which can emit one value. In our code example, I am just using it to illustrate the three notifications. In a continuous stream it will signal the end.

I hope that I’ve been able to illustrate the beauty of reactive programming and describe how RxJava can be used on Android. The ability to chain and transform async operations with hassle-free error propagation can be a powerful tool in any developer’s arsenal.


The New York Times technology team is responsible for building, maintaining and improving NYTimes.com, our mobile apps and products, and the technology that powers them. We’re a group of over 250 people, delivering content from one of the largest news organizations in the world. And we’re hiring Android developers.