Android — Jokes REST API call with Rx Java

Nicolas Duponchel
5 min readMar 28, 2018

--

If you search a way to start learning Rx ? This article is for you !

I wrote Medium stories telling some Rx Java tips I found useful (logging, errors, timeout, retry …) But I realized I never mentioned the basics. Let’s start from the beginning. I wont try to reword the Rx documentation, but tell about my own reactive programming experience with Rx.

What is Rx ?

It is an API for asynchronous programming with observable streams.

If I would quickly illustrate Rx I would take the image of a roller coaster with marbles. Rx permits to change the rails directions and the marbles’ type, color, form etc. We can observe this roller coaster’s finishing line and catch the marbles.

We can use it in many languages like Python, Kotlin, Swift, Java, JS, PHP… I’m a mobile developper so my experience belong to Rx Java & Kotlin on Android framework. But whatever, the principe is still the same.

Why should I use Rx ?

For a powerful, readable and minimal code

When should I use Rx ?

Every time I make an asynchronous operation.

Base reactive interfaces

Before starting with some examples, here is the very first thing to know : Rx base reactive types.

Rx base reactive types are Observable, Single, Completable, and Maybe.

Those 4 could be assimilated to roller coasters and their emissions to marbles.

  • Completable emits no item, just a “I’ve got the job done”.
  • Single emits a single one item.
  • Observable can emit few elements.
  • Maybe is a union between Single and Completable. It emits one or no item.

Notice that since Rx 2, reactive types does not accept nullable values. This also means that tey will never emit null.

Basic Hello World example

Let’s build a simple HelloWorld using Rx. We need 2 things to make it works :

  • The observable that will emit a String “HelloWorld”
  • The observer that will subscribe to the observable emission.

To create an observable instance, we basically use just operator. It converts an item into an observable that emits that item. Our result is a single “Hello world” String, so the observable source would be a Single.

Single.just( "Hello World" )

Now that we have an observable ready, we just need to subscribe to it’s emission.

fun helloWorld() {
val observable = Single.just("Hello World")

observable.subscribeBy(
onSuccess = { print(it) },
onError = { }
)
}

Moreover, we can choose the thread which will take the subscription responsibility, so basically we choose a non-UI Thread. Then when our observable emits a result, we will observe it on the main Thread to update UI.

observable
.subscribeOn(Schedulers.io())
.observeOn(AndroidSchedulers.mainThread())
.subscribeBy(
onSuccess = { print(it)},
onError = {}
)

Of course this example do not really matter because there’s no need of asynchronous task to write a HelloWorld ! But now that you’ve got the very basic framework, let’s try little more complex examples.

I built a simple Android app to illustrate the following ( Completable, Single and Observable) examples. Here is the GitHub repo. I implemented all those with an Activity and its ViewModel using LiveData.

Completable example

This time, we won’t care about task’s result. What matters is simply that our job succeed (or not). The most simple example I found to illustrate Completable consists on simulating an installation of something (doesn’t matter what). So let’s simulate an installation that takes 3 seconds.

Completable.timer(3, SECONDS)
.subscribeBy(
onComplete = { toast("Fake installation succeed") },
onError = { toast("Let me guess this never happen") }
)

Cool don’t you think ? Hum… I know you want to do stuff more interesting am I wrong ? So to deal with real asynchronous task with more fun, I suggest to try this RESTful public api that returns a random joke. Let’s see how Rx could help.

API call prerequisite

This paragraph explains quickly how to call a REST API on Android. Just skip it if you cannot wait to deal with Rx !

{ 
"type": "success",
"value": {
"id": 530,
"joke": "Chuck Norris can dereference NULL.",
"categories": ["nerdy"]
}
}

Here is the Json result. Let’s create a Joke class and get it from the api. Then the basics to call this URL with Retrofit :

private fun createService(): ApiService = Retrofit.Builder()
.baseUrl("http://api.icndb.com/")
.addConverterFactory(GsonConverterFactory.create(gson))
.addCallAdapterFactory(RxJava2CallAdapterFactory.create())
.build()
.create(ApiService::class.java)
interface ApiService {
@GET("jokes/random")
fun randomJoke(): Single<ApiResponse>
}
data class ApiResponse(
@SerializedName("type") val type: String,
@SerializedName("value") val joke: Joke)
data class Joke(
@SerializedName("id") val jokeId: Int,
@SerializedName("joke") val jokeText: String)

Single example

Api’s call is now ready, let’s create and subscribe to Single<Joke>. Notice that randomJoke() returns a Single<ApiResponse>, I use map operator to change it to Single<Joke>.

fun displayJoke() {
val apiService = createService()

val jokeObservable: Single<Joke> =
apiService.randomJoke().map { it.joke }

jokeObservable
.subscribeOn(Schedulers.io())
.observeOn(AndroidSchedulers.mainThread())
.subscribeBy(
onSuccess = { print(it.jokeText) },
onError = { print(it) }
)
}

Why not to add loaders to highlight the background execution ? Methods doOnSubscribe and doFinally can be used to call specified action before subscription and after onSuccess or onError.

jokeObservable
.subscribeOn(Schedulers.io())
.observeOn(AndroidSchedulers.mainThread())
.doOnSubscribe(joke_loader.show())
.doFinally(joke_loader.hide())
.subscribeBy(
onSuccess = { print(it.jokeText) },
onError = { print(it) }
)

Cool isn’t it ? Now that we’ve seen the very tip of the Rx iceberg, I suggest to have a look at Observable.

Observable example

To deal with Observable emission, I suggest to reuse the previous example but this time we could ask for some random jokes in a single flux. Let’s convert the previous Single into an Observable with toObservable. Then, now that we have a “multi-elements” emission, repeat(count)method will help. “It returns an Observable that repeats the sequence of items emitted by the source ObservableSource at most {count} times.”

val jokesObservable = jokeApiService.randomJoke()
.map { it.joke }
.toObservable()
.repeat(3)

What’s different now ? The emission is constituted of 3 jokes. And by subscribing to an Observable, each time it emits a result, the onNext method is called with it as Joke.

jokesObservable.subscribeBy(
onNext = { println(it.jokeText) },
onComplete = { println("job done")},
onError = { println(it.message) }
)

This code will print (if no error is encountered) :

jokeText1
jokeText2
jokeText3
job done

App project on GitHub

You’ve got now the basics of Rx reactive programming! For technologie lovers, I would affirm that the best app I used to deal with is Rx Kotlin app, build on MVVM using LiveData. Please have a look at the all project on GitHub.

Thanks for reading !

For those who want to learn how to unit test ViewModel in MVVM architecture : see this article.

--

--