Crunching RxAndroid — Part 4

Learning Reactive Programming the easy way

Roberto Orgiu
Crunching RxAndroid

--

In the previous article, we saw how to use Reactive Programming in a real word app, but we did not need anything else other than RxAndroid… what if we actually do need something else, combined with this amazing technology?

Retrofit

This is more or less what we want to obtain

Most probably, you all have at least heard about Retrofit from Square, that is the standard de facto for what concerns the integration of REST APIs within Android apps. Close to its second release (if you haven’t hear about it, take a look to Jake Wharton’s presentation on Speaker Deck), this library comes with the goal of making your networking calls (both synchronous and asynchronous) without any boilerplate, though clever use of Java annotations.

We obviously want to make asynchronous calls (as we already established, blocking the main thread is evil™ and it will make your app crash), noticing that you can either provide a callback to the framework, to be executed when the call ends or… make the call itself return an Observable!

So, as of now, we can imagine that Retrofit works pretty well with RxAndroid (but this is something we read on the documentation!) and we want to see with our own eyes if there is any dark magic involved in making these libraries get along.

First steps

Let’s start right away by adding the Gradle dependency to our project and synchronising the file, so that the library is downloaded and ready to use:

compile 'com.squareup.retrofit:retrofit:1.9.0'

Now that we have our environment ready, we have to understand a little bit what are the different parts of our implementation of Retrofit: first of all, we need an endpoint, that will be the URL to which we are going to make our requests; for this test, I decided to use GitHub’s API (available here), so that our base URL would be

https://api.github.com

At this point, we can declare the interface that we need in order to query the remote service. In this declaration, we will create a method for each of the calls we want to be able to make, annotating them with the relative path we want it to forward the request to:

@GET(“/users/{user}”) 
Observable<GitHubUser> getUserData(@Path(“user”) String user);

Let’s dive into these two lines: in the first one, we have the annotation that will tell Retrofit that we want to make a GET request at the path… but wait! There a strange substring in there, within a couple of curly brackets! That is a variable: we are telling Retrofit that in place of that {user}, we want the String we pass to the method as parameter, the one String that we mark with the @Path(“user”) annotation.

As an example, if we call

getUserData("tiwiz")

we are telling Retrofit to make a request to

https://api.github.com/users/tiwiz

The last part of this call is the return type and, as we can see, it is set to be an Observable: in this way, we do not need to think to provide a callback, as we can easily subscribe to the call and await for its return.

At the end of the day, our interface for two calls would look like this, with the different parts that we already explored:

public interface GitHubService {String ENDPOINT = “https://api.github.com"; @GET(“/users/{user}”) 
Observable<GitHubUser> getUserData(@Path(“user”) String user);
@GET(“/users/{user}/repos”)
Observable<GitHubRepo[]> getRepoData(@Path(“user”) String user);
}

Now, we have to create the Retrofit service that will make the calls when we need it. In order to do so, we can use the fluid syntax of the appropriate builder:

RestAdapter adapter = new RestAdapter.Builder()
.setEndpoint(ENDPOINT)
.build();
GitHubService gitHubService = adapter.create(GitHubService.class);

Note: starting from version 2.0.0, as of the time of writing, you could find yourself using something like (this is still in development, though)

Retrofit retrofit = new Retrofit.Builder()
.baseUrl(ENDPOINT)
.build();

GitHubService gitHubService = retrofit.create(GitHubService.class);

Making the call

Once we declared the service and the interface, we can think about using the API: as an example, I took a few friends of mine and I wanted to know some of the data they stored on GitHub.

To do so, we firstly emit each one of them:

Observable.from(interestingUsers)

then, we chain the call, using a flat map operator to change the type of the Observable itself:

Observable.from(interestingUsers)
.flatMap(gitHubService::getUserData)

As we already saw in a previous article, the method reference is the equivalent of the following lambda expression

user -> githubService.getUserData(user)

that is the shorted version of the Func1 declared as:

new Func1<String, Observable<GitHubUser>>() {
@Override public Observable<GitHubUser> call(String user) {
return githubService.getUserData(user);
}
}

We are almost done and what we need to deal with delivering the result on the main thread:

.observeOn(AndroidSchedulers.mainThread())

and use our GitHubUser data in the Subscriber.

Conclusion

We managed to use Retrofit with RxJava and it was fairly easy but, as we used it in the example (that you can find on GitHub), there are a couple of open points worth exploring in the future, one of which being the possibility of leaking stuff if the user quits the Activity before the Retrofit request is finished. Stay tuned for scenes from next episode…

Fun fact

What makes Retrofit work in this very elastic way, is one very powerful Java feature called Dynamic Proxy Class, which lets a class implement a list of interfaces specified at runtime. If you wish to know more about this interesting, feel free to take a look to this article and this issue.

Thanks

to my friends Eugenio Marletti, Sebastiano Poggi, Mario Viviani, Sebastiano Gottardo and Mark Allison for letting me use their data for the example and for proof reading this article.

--

--