Posted on

Android Better Networking w/ RxJava pt 2


Android RxJava
Designed by Freepik

 

Hey guys, in the previous post we learned how to make your basic networking cleaner with RxJava for Android. This library is extremely great for complex multiple network calls depending on each other’s success state. What we have today is using library with Retrofit and Firebase

 Retrofit

Retrofit itself is super easy and clean to use. The main use case for using RxJava with it is when you want to modify received data in a nice chain way. And if you want to make multiple networking which is rather weird for Retrofit because most likely api’s are optimized for single network call only. But we still can make that, what if we cannot change backend api’s, but we want to have something original creators didn’t plan for?

Something like TMDB api. They have a discover endpoint which returns list of movies for you query. Those don’t have all fields that the whole movie model has, if you want to retrieve full info – you’ll have to use their details endpoint for a particualr movie. And though they provide enough query parameters for, let’s say filtering/sorting by those fields, what if there’s no query for this field that we want? We’ll have to make second network call for each movie. Of course, that’s not the smartest way, to make bunch of network calls. But for example using RxJava with Retrofit will work. We have a production_company field in details endpoint and we want to let users apply those filters like: only Universal Pictures, Dreamworks etc. Crazy, isn’t it?

Setup Retrofit

Generally your Retrofit return Call<T>, in order for us to use it with RxJava we need to have an Observable<T>. Just add this dependency

and

for your Retrofit.Builder and you can change return value to Observable<T>.

 Multiple Api Calls

We can make as many network call in a chain as we want. But of course it’s going to affect the speed. In the example below we fetch list of movies, for each one we make api call to get production companies, set them on a movie object and return modified list of movies.

Most likely you won’t ever need to use make extra networking call for each item in a list. This would be a disastrous api, but you can can still do it easily.

Firebase

Finally we got to the place where RxJava helps a lot! Backend Api’s you can optimize, bundle everything into one if possible. With Firebase you can put everything into one json object, to reduce number of listeners to set up. Like you can get all the information you need about entity in just one table. Still this could be inefficient, redundant. And you will still have multiple entities, for which you will make set different listeners. And what if you need to update multiple tables sequentially? Something like registration process. They do depend on each other’s success, so you’ll end up having bunch of nested callbacks to retrieve result and do next call with it.

Regular Approach

We have three actions: create new user with email, upload picture to storage, save user to database. All of them depend on each other, we don’t want to retrieve result of each. It has two problems. First – nesting callbacks, even if you extract to methods, it doesn’t help so much. I won’t put the whole code in here, just the hierarchy.

Second: those horrible method names with multiple actions in it. You see, you can’t name a method with one action, but it will make many. The top level name of it is pretty abstract  – sign up. But in the first onComplete callback we upload picture, get its url and save user with name, url. We could rename uploadAvatarAndSaveUser into saveUser, but you wouldn’t understand the meaning of this method without going through the code or worse – writing comments.

pretty dumb, isn’t it?

RxJava Solution

What we would want is to those methods return values in a synchronous simple way.

Clean, readable, perfect. We could do it with Firebase api’s in background thread, but not with callback driven approach. And the whole code is a mess. Unreadable, despite extracting methods, it still is bad. Fortunately, we’ve got RxJava! I’ll use this library for Firebase support. Few trial, error and look what I got. Boom!

How

Isn’t that perfect? Just a simple imperative looking networking, when it’s asynchroous. Once again, we could do the same thing with Firebase API and running in a background thread. It would look just the same three methods. But what if you don’t want to use the api and still want your code to be readable? Here’s the solution. Underneath there’s still RxJava chain, I just broke it down with saving reference on each step into field variables. In my case I created distinct object model to store those fields.

How does the chain work? There’s a return value on each method. So we can make use of that by saving it and accessing from there. I could just make my methods return them and don’t save to fields, but it wouldn’t look so cool and you would have to pass them as parameters. Lame.

Conclusion

Definitely, RxJava provides ways to improve, make more readable, cleaner our code. At first times you might think: why do I need to learn something if I get the job done without it? As for me, I think it’s readability and not having to write comments for people to understand the meaning easily. But you might have a hard time with the library at first time when you want to make the real use of it. But it worth to spend time learing it

Alright, thanks for reading, you can get source code here. I encourage you to check it if you haven’t user RxJava especially to see the difference between with and without it. Don’t forget to subscribe, follow me on G+, Facebook, Twitter and share with friends if you think they will benefit from it!