The Essential RxJava Guide for Android Developers


By Jim Baca

 Android Developer, Public Speaker, Tango Dancer, & Ginger Beer Enthusiast

Introduction

pasted image 0 4

As Android Developers we have tons of choices when it comes to handling concurrency. Which one do we choose? This guide focuses on ReactiveX for Java (RxJava).

This is not just another blog post nor just a RxJava tutorial. This is a full blown ultimate guide about learning RxJava. This guide is over 7000 words long.

It breaks down the anatomy of Rx to make it easy to conceptualize. It contains video, it has diagrams, It has references to useful libraries.

Actually I lied most of the sample code is written in Kotlin. What can I say? I love Kotlin. If you are still using Java for your Android development fear not everything in this guide still applies.

That’s because we still use the RxJava library. While we do use RxKotlin. RxKotlin acts as a supplement. You can think of RxKotlin as sitting alongside RxJava enhancing it (not replacing). This gives us some additional convenience functions. RxJava works out of the box with Kotlin.

Before we get started.  Take this 9,586 word must have RxJava guide for Android Developers with you. Get it here ->

Why I wrote this guide

pasted image 0 10

I’ve seen the looks of confusion from developers who have never used Rx before. I’ve seen these looks of utter confusion and bewilderment in conferences. I remember experiencing it first hand.

I’ve seen developers get overwhelmed because they don’t get it initially. They think that they have to spend tons of time to learn Rx. I’ve even seen them turn away because the learning curve appears too steep.

I get it. When you have deadlines it becomes impossible to justify learning something new. It’s more difficult when you aren’t sure if the payoff is worth it.

Just the way Rx is described can be off putting to developers. I hear “Functional Reactive Programming” to the uninitiated this doesn’t help.

My goal is for this guide to be the intro that I needed back in 2014. Instead of focusing on definitions this guide is designed around the why, followed by the how.

I should mention that this guide is from a 2017 perspective since RxJava v1 is on its way out (it’s being succeeded by RxJava v2).

I will start out by answering why RxJava is important from an Android Developer perspective. I will then give a bird’s eye perspective of the different RxJava parts. This is to make it easier to conceptualize how all the pieces fit together.

Then I will dive into each component in more detail. Since you will have already had the bird’s eye perspective you will not be confused when other parts of RxJava are brought up since they are all connected.

Last but certainly not least, I will cover useful things to know and things to watch out for to save you debugging time.

Thanks

I’d like to thank Patrick Dattilio for proofreading and his suggestions. I’d like to thank Chris Arriola and Angus Huang as well. If you like reading about Reactive Programming on Android with RxJava check out their book here. I read it, liked it and I am not making any money by endorsing it.

Table Of Contents

Chapter 1 — Who Am I

Chapter 2 — Why All Android Developers Should be Using Reactive Extensions for Java

Chapter 3 — The Bajillion Other Reasons Why Android Developers Should Be Using Reactive Extensions

Chapter 4 — Why All The Other Concurrency Options Suck

Chapter 5 — Rx Appetizer

Chapter 6 — The Producers: Flowable, Observable, Single, Completable, Maybe?

Chapter 7 — Shape Shifting Data

Chapter 8 — Side Effect Methods

Chapter 9 — End of The Road

Chapter 10 — Slamming On The Brakes

Chapter 11 — Work Here, Work There, Schedulers Everywhere

Chapter 12 — Converting Existing Code to Rx

Chapter 13 — Time Traveling with RxJava

Chapter 14 — Must Have Libraries

GUIDE ON THE GO
Get this FREE 7000+ word guide as a pdf, so that you can take it with you and read it on the go.


 I'll teach you about RxJava so that you can:
  • Write better android apps
  • Handle concurrency easily
  • Take full advantage of useful Rx libraries


I'll even throw in an extra chapter on common mistakes, and how to avoid them.

Chapter 1

Who Am I

pasted image 0 9

I’m Jim Baca. I graduated with a degree in Computer Science back in 2005. I worked as a web developer until 2010 when I decided to become an Android Developer. I went from struggling to get projects to working on major projects for Paramount, Qualcomm, and most recently Major League Baseball (In their Advanced Media Division).

When I first started Android development, I quickly realized there were a lot of pitfalls. As a result I’ve always had the habit of looking for easier ways of programming for Android. This has the side benefit of improving the way in which I create Android applications.

Back in 2014 I snuck out of one conference in San Francisco and hightailed it to React Conf. I was so excited because I read about all the amazing features of Rx(Reactive Extensions). But the learning curve back then was even steeper. I understood the benefits, but I wasn’t quite sure how Rx worked.

Comparatively there were fewer opportunities to learn about Rx. I remember sitting in a workshop on “Building Reactive UIs With Rx”. I was seeing the useful things that Rx could do. But I didn’t understand it. I seen the same looks of confusion when others are picking up Rx for the first time.

Back in 2015 I realized that there had to be a better way of handling concurrency on Android. I’m glad I found Rx and hope to help others learn.

Chapter 2

Why All Android Developers Should be Using Reactive Extensions for Java

pasted image 0 24

To understand the need for RxJava we need to look at the underpinnings of the Android operating system. To understand that we should first look at hardware requirements. Since Android devices have limited resources it has to be a way to start and stop apps to free up resources.

This created the need for the Activity Lifecycle methods. We can think of these as a contract between the OS and apps to give feedback about the activities’ current stage. The initial thought might be to do whatever work is needed in one of the lifecycle methods not taking into consideration how much time it will take to execute that code. If the work is rather extensive then this is a bad solution as it slows down the processing of the Activity Lifecycle.

This is because the Activity Lifecycle is run on the Main Thread. The Main Thread is responsible for lots of things like updating the UI, handling touch events, and of course the Activity Lifecycle methods.

Slowing down the Main Thread causes sluggish apps. If you slow down the Lifecycle methods then you slow down the Main Thread, which means sluggish apps.

In earlier versions of Android It was possible to do networking requests on the Main Thread. This led to slow and sluggish apps and angry users. Later on Android prohibited doing network requests on the Main Thread and instead would throw a network on Main Thread Exception.

That of course means we need to get the work off the Main Thread. Here is a visual representation of what we’ve covered so far.

Untitled Diagram

Moving work off the Main Thread does not solve all of our problems. It is easy to leak memory by having a reference to a Context (often times an Activity in particular).

Having a reference to an Activity is not bad in and of itself. It only becomes bad when the reference extends past the activity’s life cycle.

It’s bad because holding on to the Activity keeps it from being garbage collected. Since activities can use lots of memory this is a problem.

This is a common problem when using AsyncTask. Colt McAnlis gave a fantastic talk about concurrency at the Austin Droids meetup in which stated AsyncTask should be used for tasks that take 2 milliseconds or less.

Since 2 milliseconds is a crazy short amount of time, you can see how easy it would be to violate that principle. And when you do that then you run the risk of running into an IllegalStateException.

Which uncaught becomes an application crash. Much to the frustration of your app users.

For me there is nothing worse than getting the popup saying an app has crashed when I wasn’t even actively using that particular app.

Picture this, you are using amazing app, then you need to check your email. So you open the gmail app.

pasted image 0 21

While you are checking your email you get the annoying popup that amazing app has crashed. We’ve all been there, it sucks. We immediately start thinking how bad it is that an app that isn’t even actively running is crashing. Amazing app can’t even manage to crash while I’m using it. Garbage.

Angry Users

pasted image 0 23

Understandably this leads to angry users. Which leads to bad reviews. Which leads to fewer users.

The great news is that RxJava solves these problems. It gives an easy way of handling concurrency, and an easy way of stopping.

What About Architecture Components?

If you were also at Google I/O 2017 or were watching you might have noticed that Architecture Components were introduced. You might be asking yourself doesn’t this make Rx pointless on Android?

For some developers they are a bit controversial because they expose lifecycle events further. They were hoping that Google would have provided a solution to allow developers to not care about the lifecycle.

Since they are so new, it will be interesting to see how they are regarded in the coming months. Fragments were very controversial.

Google has also pointed out if you have architecture that works, it’s fine to keep using it. There isn’t a mandate to change.

However, If you opt to use the Architecture Components all of the wonderful features of Rx can still be used. Architecture Components showing up just means that there is another option for handling issues that arise from combining life cycle and concurrency.

In fact during the Architecture Components Introduction they actually mentioned Rx. They said that if you like Rx you can use Rx with Live Data or Room Architecture Components. Which brings us to the other reasons why you should be using Rx.

Chapter 3

The Bajillion Other Reasons Why Android Developers Should Be Using Reactive Extensions

pasted image 0 13

Okay maybe not a bajillion but if you go through all of the different operators you’ll find that there are tons and tons of different ways to manipulate data in useful ways. In this section we will show more reasons why you should use Rx.

Don’t feel bad if you don’t understand the code. Revisit it after you’ve read the other sections about Rx anatomy. It’s good enough just to understand why it’s useful.

The first one that I encounter so often is data manipulation or transformation. It’s common that data from a web request needs to be changed. Maybe you get a slightly larger data set and you only want some of it.

For example if we are receiving a data payload:

data class ResultPayload(val data: ResultSet, val pagesAvailable: Int, val resultsPerPage:Int)

We only want the ResultSet items:

data class ResultSet(val date:DateTime, val items: ArrayList<Content>)

Even more specific we only want the important data for today:

data class Content(val title:String, val content:String, val url:String, val date: DateTime)

We could write the following

observer = service.getData()
       .flatMap {
               Observable.fromIterable(it.data.items)
       }
       .filter { it.date.isToday() }
       .toList()
       .observeOn(AndroidSchedulers.mainThread())</p>
       .subscribeWith(object: SingleObserver<List<Content>>{
                   override fun onError(e: Throwable?) {
                              // handle error
                   }
                   override fun onSuccess(t: List<Content>?) {
                              // do some ui work maybe display in a RecyclerView
                   }
                   override fun onSubscribe(d: Disposable?) {
 
                  }
})

Data Manipulation

First thing we do is make the stream focus on individual items. Instead of performing work on the collection as a whole we can break it into individual items. From there we can filter out each item that isn’t today. After that we can collect all of those items back into a list.

We can then do something with the resulting data. Such as putting it in an Adapter for a RecyclerView.

Request Chaining

Another useful example is request chaining. Many times you have to make sequential networking requests that you want to combine together. Because you only want one result or one error.

Here is a sample of what this might look like using Retrofit. The first request is a fetch for an ID and the second is a request for the data that that id represents.

observer = service.getMatchingIds(“search term”) // Request for ids
       .flatMap {
           Observable.fromIterable(it.data.id) // convert the stream to focusing on ids
       }
       .flatMap { service.getContent(it) } // convert the stream to focusing on Content items
       .tolist() // group the resulting items into a list
       .observeOn(AndroidSchedulers.mainThread())
       .subscribeWith(object: DisposableObserver<List<Content>>(){
   override fun onComplete() {
       // Update the UI to signal work completion
   }
   override fun onError(e: Throwable?) {
       // handle an error
   }
   override fun onNext(t: List<Content>) {
       // Do some work
   }
})

I would just like to point out that you can chain together as many of these operators as you need. There are lots of ways of combining them.

Callback Hell

pasted image 0 1

With the traditional callback pattern callbacks become very messy when chained. Especially if you have to propagate errors up the callback chain. Koushik Gopal calls this callback hell, and I’d definitely agree. It gets messy very quickly.

If an exception is thrown during the execution of Rx it will be returned in onError. That covers any part of the RxJava chain.

With the traditional callback pattern you have to go through a lot of work to propagate errors back to the original callback.

RxJava allows you to put all error handling logic in one place. It allows you to not worry about error propagation, it does that for you.

Now I want to discuss why other concurrency options are not as viable.

Wait! Don't miss out.  Take this 9,586 word must have RxJava guide for Android Developers with you. Get it here:

Chapter 4

Why All The Other Concurrency Options Suck

pasted image 0 2

I was in a wonderful Rx talk given by John Petito. In the talk he pointed out all of these concurrency options we as developers have:

  • Callbacks
  • AsyncTask
  • Handlers + Loopers
  • Threads

Unfortunately none of them address all of the issues we have discussed. They don’t offer easy request chaining, nor do they have easy ways of handling errors.

While they do handle concurrency they often don’t have the ease of specifying where work is to be done, nor do they offer ways of changing where work is done with operators. Lastly they don’t have the ease of stopping work.

While they may offer some of the benefits of Rx they don’t cover them all.

class MainActivity : Activity() {
 
   ...
 
   // At some point MyAsyncTask is created and started
 
   inner class MyAsyncTask : AsyncTask<Void, Void, String>() {
 
       protected fun doInBackground(vararg params: Void): String {
           // Do long running operation work
           return result
       }
 
       protected fun onPostExecute(result: String) {
           // Update UI now that work is complete
       }
   }
}

The above class MyAsyncTask has an implicit reference to MainActivity. This means that MainActivity will not be garbage collected until MyAsyncTask is completed.

You may remember that AsyncTask has a cancel method. But guess what, it’s up to you to periodically check if it should stop doing it’s background work. This is achieved by calling the isCancelled method in doInBackground and bailing.

I don’t know about you but I’d rather focus on app specific logic rather than repetitive platform prone problems.

class MainActivity : AppCompatActivity() {
 
   ...
 
   public class MyAsyncTask: AsyncTask<Void, Void, String>() {
      
 
       override fun doInBackground(vararg params: Void?): String {
 
           while(!isCancelled){ // constantly check here to see if cancelled
               doWork()
           }
          
           return // some result from work
       }
}

To be fair the memory leak itself isn’t a problem with AsyncTask. Let’s say that we don’t make the class inner so that there isn’t an implicit reference. Then we have to pass in a callback (such as the activity) and clear it out to not leak memory:

class MainActivity : Activity() {
 
   ...
   override fun onStop() {
       super.onStop()
       task.clearCallback()
       task.cancel()
   }

   // At some point MyAsyncTask is created and started
 
   class MyAsyncTask(var callback:MainActivity?) : AsyncTask<Void, Void, String>() {
 
       override fun doInBackground(vararg params: Void?): String {
 
           while(!isCancelled){ // constantly check here to see if cancelled
               doWork()
           }
          
           return // some result from work
       }
 
       protected fun onPostExecute(result: String) {
           // Update UI now that work is complete
       }
       public fun clearCallback() {
           callback = null
       }
   }
}

That means for every AsyncTask we need to:
1) Pass in a callback as a variable (so that we can clear it out to prevent a memory leak e.g. during onStop)
2) Tell the AsyncTask to cancel (so that we aren’t doing pointless work that isn’t going to be used)
3) Periodically check if isCancelled is set to true (again so that we aren’t doing pointless work)

RxJava in contrast only needs to have dispose/cancel called. The other pieces are handled by Rx.

For example some RxJava might look like:

class MainActivity : AppCompatActivity() {
   lateinit var observer : DisposableObserver<Account>
  
   override fun onStart() {
       super.onStart()
       observer = service.getAccount(“id”).subscribeWith(object: DisposableObserver<Account>(){
           override fun onComplete() {
               // Update the UI to signal work completion
           }
           override fun onError(e: Throwable?) {
               // handle an error
           }
           override fun onNext(t: Account) {
               // Do some work
           }
       })
   }

   override fun onStop() {
       super.onStop()
       observer.dispose()  // <--- this is the crucial line that allows us to easily stop
       // instead of constantly checking if we should have to stop like in AsyncTask we tell it to stop
       // it's that simple
   }
}

If you notice onStop has an observer.dispose(), that’s all we need to do to stop doing work. No need to worry about leaking the activity (specifically large amount of memory) nor worry about accidental attempts to update a UI that is no longer present.

I’m sure if you are a diehard AsyncTask fan that you could write additional code to cover these additional requirements. But at that point you aren’t focusing on solving app specific problems but rather shoring up the shortcomings of AsyncTask.

Coupled with the other features previous mentioned it’s not surprising why so many Android Devs love RxJava.

Chapter 5

Rx Appetizer

In this section I am going to treat RxJava like an Appetizer. I will give a lite introduction to the different parts. In subsequent sections I will dive deeper into specifics for each.

The goal is for you to have a high level overview.

Since each component works with others it’s important to understand the basics of each. That way when we are delving into more specifics and mention another component that isn’t the main topic you aren’t lost.

Let’s get started with producing data. It helps to compare this to an existing design pattern. For that let’s start with the observer design pattern.

In the observer design pattern there is a subject that maintains a list of observers. The subject notifies observers of any state changes. In the context of Rx you can think of producers as being the subject. Producers will notify their observers when state changes.

This is how data is produced. Originally there was one producer, called the Observable. Observable generates data and passes it on. It’s really that easy.

Observable isn’t the only producer. There are others that are very similar they just produce more or less data. But we’ll cover that more in detail later.

Next we have Operators which transform data. They take data that an Observable or another Operator produced and modify it in some way. There are lots of different operators that can alter the data in many ways.

Next we have Subscribers you can think of them as consumers or as callbacks. They handle the results of work. This is where you typically react to work being done. Think of updating the UI after getting the results back from a network call.

A Subscription represents work that is being done. With a subscription it’s possible to see if the work is completed, as well as cancel the work. Being able to cancel work is one of the crucial convenience factors we discussed in the beginning of the guide.

That leaves us with Schedulers, Schedulers represent where work (i.e. the producers like Observables as well as Operators) and result processing (i.e. Subscribers/Disposable) are done.

Component What it does
Subscription Represents some work being done, able to check if it’s done or cancel it
Flowable, Observable, Single, Completable Do work of some sort
Operators Modify data
Schedulers Where work is done UI thread etc
Subscriber/Disposable Where results of work is sent
Wait! Don't miss out.  Take this 9,586 word must have RxJava guide for Android Developers with you. Get it here:

Chapter 6

The Producers: Flowable, Observable, Single, Completable, Maybe?

pasted image 0 8

All of these do work and produce data. The big difference between most of them in RxJava v1 is how much data they produce. It’s easiest to view them in a chart:

RxJava Version 1

Name Units of Data Produced
Observable Multiple or None
Single One
Completable None

It is worth noting that Single and Completable were added very late to RxJava. As a result, it’s not uncommon to see Observable used where Completable or Single should be.

You should always use the most appropriate producer type. Using the wrong producer is a bad practice as it’s misleading. Imagine a function that says it always returns an Array but always returns null.

If you encounter code like this, it is likely because the code was written before Single and Completable were added to RxJava. Or because the developers were not aware of Single and Completable as a result of them being added so much later.

RxJava Version 2

Name Units of Data Produced
Observable Multiple or None
Flowable Multiple or None
Single One
Maybe One or None
Completable None

The first question that comes to mind after seeing the table is what is the difference between Observable and Flowable? One problem that RxJava encountered early on was backpressure.

Backpressure

Backpressure is when data cannot be processed as quickly as it’s being created. Think of the I Love Lucy Episode where she goes to work at the Chocolate Factory. Her job is to wrap the chocolates.

https://www.youtube.com/watch?v=HnbNcQlzV-4

At first she is able to keep up, but eventually there is too much chocolate (think data). And she resorts to various means of handling the pressure.

Backpressure is when an Operation or Subscriber cannot process data fast enough, causing other work further up the Rx chain to backup.

RxJava initially wasn’t designed with backpressure in mind, it had to be added later. Retrofitted is actually a better way of describing it because developers unfortunately needed to use specific operators to get back pressure support.

This often was overlooked leading to a MissingBackPressureException being thrown at runtime. With RxJava v2 Observable doesn’t have any back pressure support. Instead Flowable was introduced which has backpressure support.

When to use Flowable v. Observable. Or rather when you need backpressure or not. This comes down to the type of work you are doing.

If you are making a one off web request then you are only handling one item so an Observable would work. If you are doing UI work like processing UI events then you likely need to keep up to date because you don’t want to process events late and make the app appear sluggish. In those cases you likely want to have a sampling or debouncing strategy.

Flowable is good for processing large numbers of events when you can control the rate of events generated. For example if you are doing file reading you can control how many lines to read, or if you are doing a database query you can control how many rows are read. Essentially if it’s a large amount that is easy to create a pull strategy.

Single is similar to Observable but it must return either one item or an Error. Therefore there is no onNext in the single subscriber. It’s completed the moment the single item is received via the onSuccess method.

Completable is good for when an asynchronous action needs to take place but no result is expected to be returned. Think of making a web request to POST some data. If all you are concerned with is that the POST was successful or not then Completable is ideal. It has two possible outcomes onComplete and onError.

Maybe is interesting. Maybe didn’t exist in RxJava v1. It is essentially a Completable or a Single. It may return 1 item or it may complete.

Hot versus Cold Observables

pasted image 0

At some point in time you may come across this phrase and be really confused about its meaning. This reminds me of the “If a tree falls in the forest and no one is there to hear it does it make a sound?”

If we reword it slightly we can come up with this: If an observable can generate a value and no one is there to observe it should it have generated it in the first place?

Rx supports both. If an observable can generate values without a subscriber being present it’s called a hot observable.

If on the other hand the observable doesn’t begin work until it has been subscribed, then it is considered a cold observable.

Let’s take a look:

val observable = rx.Observable.interval(1, TimeUnit.SECONDS)
Thread.sleep(5000)
val subscription = observable.subscribe{ i-> System.out.println("From First: " + i)}
From First: 0
From First: 1
From First: 2
From First: 3
From First: 4

As we can see the cold observable did not start emitting items until subscribed no matter what the delay is from subscription.

In contrast a hot observable will start emitting once connect is called. If we still sleep the same amount of time we will find that we do not get the same output.

Let’s take a look:

val observable = rx.Observable.interval(1, TimeUnit.SECONDS).publish()
observable.connect()
Thread.sleep(5000)
val subscription = observable.subscribe{ i-> System.out.println("From First: " + i)}
From First: 5
From First: 6
From First: 7
From First: 8
From First: 9

In our hot observable example we used convenience methods for creating a ConnectableObservable. This ConnectableObservable doesn’t start emitting items until the connect method is called. But once it does items are emitted regardless of a subscription being present.

Chapter 7

Shape Shifting Data

pasted image 0 22

With RxJava there are tons of ways of modifying data. We have lots of functions for different ways of modifying
data. They are referred to as operators.

One pattern that I see frequently is json data we are interested in is filtering nested data. We often want to pull out only some of the encapsulated data. Let’s say that our use case is to make a request for the top page, from there we want to get the data for the top page. We have to make two requests.

https://www.reddit.com/r/androiddev/top/.json?limit=1

{
  "kind": "Listing",
  "data": {
    "modhash": "v0zppdjxht40e17c511ce4c98542b11ef2d76810acd7fd8520",
    "children": [
      {
        "kind": "t3",
        "data": {
          "contest_mode": false,
          "subreddit_name_prefixed": "r/androiddev",
          "banned_by": null,
          "media_embed": {},
          "thumbnail_width": 140,
          "subreddit": "androiddev",
          "selftext_html": null,
          "selftext": "",
          "likes": null,
          "suggested_sort": null,
          "user_reports": [],
          "secure_media": null,
          "link_flair_text": null,
          "id": "6lvih6",
          "view_count": null,
          "secure_media_embed": {},
          "clicked": false,
          "report_reasons": null,
          "author": "DevAhamed",
          "saved": false,
          "mod_reports": [],
          "name": "t3_6lvih6",
          "score": 39,
          "approved_by": null,
          "over_18": false,
          "domain": "github.com",
          "hidden": false,
          "preview": {
            "images": [
              {
                "source": {
                  "url": "https://i.redditmedia.com/Xf7eS5J_RQzvcHNNo6ImhPhenea7-5FK1mfU-hl0OsQ.jpg?s=a6159a6e982c24e62ff5dbdc4d233c2a",
                  "width": 234,
                  "height": 234
                },
                "resolutions": [
                  {
                    "url": "https://i.redditmedia.com/Xf7eS5J_RQzvcHNNo6ImhPhenea7-5FK1mfU-hl0OsQ.jpg?fit=crop&amp;crop=faces%2Centropy&amp;arh=2&amp;w=108&amp;s=475af0a1a8368f036a0bbfb5b8d3c574",
                    "width": 108,
                    "height": 108
                  },
                  {
                    "url": "https://i.redditmedia.com/Xf7eS5J_RQzvcHNNo6ImhPhenea7-5FK1mfU-hl0OsQ.jpg?fit=crop&amp;crop=faces%2Centropy&amp;arh=2&amp;w=216&amp;s=54f678d426f927171d45095f7a9e9cee",
                    "width": 216,
                    "height": 216
                  }
                ],
                "variants": {},
                "id": "v5opvWy-t9mxEhVup4mRNhaZUjJlQOFpwnc6hJLwf3U"
              }
            ],
            "enabled": false
          },
          "thumbnail": "https://b.thumbs.redditmedia.com/dVZy5Obvgo6MOTP-GW5Qw6ZUUXJM7oSdEhCZQ7dUj5U.jpg",
          "subreddit_id": "t5_2r26y",
          "edited": false,
          "link_flair_css_class": null,
          "author_flair_css_class": "",
          "gilded": 0,
          "downs": 0,
          "brand_safe": true,
          "archived": false,
          "removal_reason": null,
          "post_hint": "link",
          "can_gild": true,
          "thumbnail_height": 140,
          "hide_score": false,
          "spoiler": false,
          "permalink": "/r/androiddev/comments/6lvih6/sqlbrite_v200_released_with_rxjava2_support/",
          "num_reports": null,
          "locked": false,
          "stickied": false,
          "created": 1499479945,
          "url": "https://github.com/square/sqlbrite",
          "author_flair_text": "MultiViewAdapter on GitHub",
          "quarantine": false,
          "title": "SQLBrite - v2.0.0 released with RxJava2 support, kotlin extension functions",
          "created_utc": 1499451145,
          "distinguished": null,
          "media": null,
          "num_comments": 3,
          "is_self": false,
          "visited": false,
          "subreddit_type": "public",
          "is_video": false,
          "ups": 39
        }
      }
    ],
    "after": "t3_6lvih6",
    "before": null
  }
}

The first step is to make the first request

https://www.reddit.com/r/androiddev/top/.json?limit=1

The next step is to pull out the relevant information:

Data.children[0].permalink

From there we need to make another request to get that information:

https://www.reddit.com/r/androiddev/comments/6lvih6/sqlbrite_v200_released_with_rxjava2_support.json

As we showed in the Bajillion Other Reasons why section you can easily chain requests using the flatMap operator. Revisit that section to see how.

As we stated earlier there are tons of different operators for modifying the data. In our case above we used flatMap to merge the results of our second request into the original stream.

If you have a particular problem but aren’t sure which operator to use take a look at the decision tree.

http://reactivex.io/documentation/operators.html#tree

Marble Diagrams

Once you’ve found the operator that you think you want, take a look at the marble diagram on the operator page. This will give you a visual representation of what it does.

http://reactivex.io/documentation/operators/flatmap.html

pasted image 0 19

In this case we see that the first item emitted itself can be treated as an observable and we want to add its results to the stream. This is exactly what we did in our previous example. The Red circle can represent our first request to get the top androiddev post. Then we flatmap the url to get the post data represented by the red diamond.

Wait! Don't miss out.  Take this 9,586 word must have RxJava guide for Android Developers with you. Get it here:

Chapter 8

Side Effect Operators

When I first heard this mentioned I wasn’t exactly sure what this referred to. I like to think of them as operators that do not alter the data in any way. Rather they report information about the Rx chain.

For example there is a side effect method called doOnSubscribe. It’s aptly named because this function gets called as soon as the subscription happens. I’ve used this one to trigger a loading notification to the user in the UI.

There are lots of other ones as well. The big distinction with these is to remember that they are not intended to transform the data. doOnNext for instance may be used to log data.

You should still be careful when using side effect methods. While they aren’t intended to be used for altering the stream it is possible to alter the data.

Take for instance this scenario:

observer = service.getData()
       .flatMap {
           Observable.fromIterable(it.data.items)
       }
       .doOnNext {
            // Log specific dates if appropriate
           it.date = DateTime() // overwriting the date for each item
       }
       .toList()
       .subscribeWith(object: SingleObserver<List<Content>>{
           override fun onError(e: Throwable?) {
           }
           override fun onSuccess(t: List<Content>?) {
                        // date information is no longer correct :/
           }
           override fun onSubscribe(d: Disposable?) {
           }
})

Chapter 9

End of The Road

pasted image 0 16

Consumers. What good would Rx be if it didn’t provide a way of handling the final data?  This is what Observers and Subscribers are for. Observer is an interface that implements these three methods:

onComplete()
onError(Throwable)
onNext(Object)

These are the three methods that we talked about in previous sections.

The rules of Observer and Subscriber callbacks are very simple and are essentially this:

The Rx stream will run calling onNext for each piece of data. It will keep running until it completes successfully or until an error occurs.

 

In general errors in the stream will cause onError to be called with the exception as a parameter. Again the stream will cease operating.

In contrast if no error occurred then the Rx chain will keep executing until there is no more data. At which time onComplete will be called.

It’s important to note that onError and onComplete will not both be called. This goes for any of the subscribers for other producers. It’s one or the other, never both.

For example Completable has CompletableObserver which is an interface that contains onComplete and onError. Only one of those two methods will be called, not both.

Observer vs. Subscriber in RxJava v1
What is the difference between Observer vs. Subscriber? If you look at Subscriber you will see that it not only does it implement Observer but it also implements Subscription as an abstract class.

Let’s look at Subscriptions to see what extra methods a Subscriber gains as a result:

public interface Subscription {

    /**
     * Stops the receipt of notifications on the {@link Subscriber} that was registered when this Subscription
     * was received.
     * <p>
     * This allows deregistering an {@link Subscriber} before it has finished receiving all events (i.e. before
     * onCompleted is called).
     */
    void unsubscribe();

    /**
     * Indicates whether this {@code Subscription} is currently unsubscribed.
     *
     * @return {@code true} if this {@code Subscription} is currently unsubscribed, {@code false} otherwise
     */
    boolean isUnsubscribed();

}

With Observer we can check if it is unsubscribed. We can also unsubscribe. When to use one over the other? If you need to be able to unsubscribe. If you don’t need to unsubscribe then Observer would work.

Observer vs. Subscriber in RxJava v2
Observer and Subscriber are nearly identical in v2. They are both interfaces. Where they differ is the onSubscribe method. One passes back a Disposable, and the other a Subscription. We’ll discuss the differences between the two in the next section.

Chapter 10

Slamming On The Brakes

pasted image 0 6

RxJava v2 has Subscription and Disposables that signify work being done. For the purposes of stopping work being done they both can be used.

Subscription vs. Disposable
The Reactive-Streams specification that Rx Java v2 is based off of already defined a Subscription. This meant that there would be a name conflict. Additionally the methods that the interfaces defined were different.

In particular the Reactive-Streams specification had a method called request for helping out with backpressure. Since Observable, Single, Maybe, and Completable by design does not support backpressure a Subscription doesn’t make sense.

Instead Disposable was added for these non backpressure producers. Leaving Subscription for Flowables only.

With Disposable you can check if it has been disposed via the isDisposed method. Which is very similar to the Subscription isUnsubscribed method in RxJava v1.

Since we want to stop our work before the activity lifecycle ends it’s important to dispose/unsubscribe.

The rule of thumb is to unsubscribe/dispose as early as possible. Historically in Android it used to be very common to unsubscribe in onPause.

This is because the time between onPause being called and onStop was usually trivial (and the whole unsubscribe as soon as possible guideline). Now that Android (Nougat) has multi window support multiple Activities being visible at the same time will become much more common.

As a result one of the Activities will be chilling out between onPause and onStop while the other is active.

It may make sense for your app to keep updating the UI while it’s paused because it is still visible to the user. Otherwise your app might look odd and give the user a bad experience.

Imagine in one app you are downloading a video. The video app has a progress bar to show how far it has to go to download. It’s almost done 95% of the way and you decide to check your email.

You open a second app to check your email. All of a sudden the video app stops updating the progress bar because it was unsubscribed during onPause.

You switch back the video app and are confused because the video jumps to being completed. Or worse maybe it didn’t complete because it unsubscribed during the onPause instead of onStop.

Both are bad. The point is we need to pay attention when we dispose/unsubscribe.

Kudos to Kristin Marsicano for pointing out the time between onPause and onStop being longer due to multi-window support. She has an excellent post about this here. She also has my favorite diagram of the Activity Lifecycle:pasted image 0 5

CompositeSubscription / CompositeDisposable

pasted image 0 17

In RxJava v1 CompositeSubscription was useful for collecting Subscriptions to unsubscribe. Instead of having to unsubscribe from each one, one at a time. Add each subscription to the CompositeSubscription and unsubscribe from the collection.

When it’s time to cleanup unsubscribe from only the CompositeSubscription. It’ll take care of the
rest. Voilà. Work done.

In RxJava v2 this looks like the following:

val disposable = CompositeDisposable()
disposable.add(Observable.just(1).subscribeWith(object : DisposableObserver<Int>() {
   override fun onNext(integer: Int?) {
 
   }
 
   override fun onError(e: Throwable) {
 
   }
 
   override fun onComplete() {
 
   }
}))

In RxJava v1 it looked like the following:

CompositeSubscription subscriptions = new CompositeSubscription()

subscriptions.add(Observable.just(1).subscribeOn(Schedulers.computation()).observeOn(AndroidSchedulers.mainThread()))

subscriptions.add(Observable.just(2).subscribeOn(Schedulers.computation()).observeOn(AndroidSchedulers.mainThread()))

subscriptions.clear()

I have to point out that CompositeSubscription has two methods for unsubscribing. The first is unsubscribe the second is clear. When you unsubscribe from a composite subscription you can’t reuse the composite subscription.

RxJava v2 aims to match the Reactive-Streams specification, this is why the method signature of the subscribe method returns a void in RxJava v2. 

In RxJava v2 Disposable was added. This was a result of the difference between Flowable and NonFlowable subscribers.

Name Subscriber Name
Flowable Subscriber
Observable Observer
Single SingleObserver
Maybe MaybeObserver
Completable CompletableObserver

It’s worth pointing out that there are a convenience classes for each of the Observer variations. They are prepended with the name Disposable. They are abstract classes that expose the Disposable functionality without you having to keep track of the variable returned in onSubscribe.

It’s also worth pointing out that subscribe now returns void in RxJava v2 due to it adhering to the reactive stream specification. In v1 it the subscription was returned from subscribe allowing you to easily cancel the work. To bridge the gap a subscribeWith method was added in v2. This does the same thing as subscribe but also returns the Subscriber/Observer object similar to the subscribe from v1.

Wait! Don't miss out.  Take this 9,586 word must have RxJava guide for Android Developers with you. Get it here:

Chapter 11

Work Here, Work There, Schedulers Everywhere

pasted image 0 12

The concept of schedulers is very easy. They determine where work is done and where results are evaluated. Alternatively you can think of them as specifying where work (such as a background thread) is done and where results are delivered (such as a UI thread).

As discussed in the beginning one of the problems we discussed was handling concurrency. RxJava has the useful feature for scheduling where to do the work. Think of AsyncTask doInBackground method, except with more control. Observables have a method called subscribeOn for controlling this.

subscribeOn specifies where the work is done. Let’s look at an example:

Observable.defer(...).subscribeOn(Schedulers.computation()).observeOn(AndroidSchedulers.mainThread()).subscribe(...)

This code will do the actual work (what’s in defer) on the Computation scheduler. This means that we’ve moved the work off of the main thread.

When we get the result we probably want to update the UI so that the user knows that the work is done. This is accomplished with the observeOn method. This time we used AndroidSchedulers.mainThread() so that we can update the UI without running into the CalledFromWrongThreadException.

The rules regarding subscribeOn and observeOn. observeOn can be called multiple times with different schedulers. This will cause different parts of the chain to run with different schedulers.

Observable.interval(1, TimeUnit.SECONDS) // by default this runs on the computation scheduler
       .map { it * 2 } // runs on the computation scheduler
       .observeOn(Schedulers.io())
       .filter { it % 3L == 0L } // runs on the io scheduler
       .observeOn(Schedulers.computation())
       .subscribe()

subscribeOn however is different. It can only be called once. The first call wins. For example the following:

Observable.defer(...).subscribeOn(Schedulers.computation()).observeOn(AndroidSchedulers.mainThread()).observeOn(Schedulers.computation()).subscribe(...)

The observable ran on the Computation Scheduler because it was the first one in the chain. The second subscribeOn does nothing, and no error is generated either.

I should point out that AndroidSchedulers isn’t in the RxJava library but the RxAndroid library.

Chapter 12

Converting Existing Code to Rx

pasted image 0 3

Let’s look at how to convert asynchronous code and synchronous code to Rx. First let’s look at how to convert synchronous code to Rx.

First we will need the code that doesn’t yet use Rx. This could be an older library or some function that you want to work on a background thread. First we need to create an Observable.

In RxJava v1 the create method caused lots of problems because it was often used incorrectly. One error that I’ve seen frequently is that work ends up being done on the main thread instead of on the intended scheduler. RxJava v2 has been designed to safeguard against this. Since RxJava v1 is near EOF let’s look at RxJava v2 code:

Flowable.create<Int>({ emitter->
   emitter.onNext(expensiveFunction())
   emitter.onComplete()
}, BackpressureStrategy.BUFFER)

Here we are creating a Flowable, when we subscribe to it then the work gets kicked off on the appropriate scheduler. Which will cause the expensiveFunction() to be called.

Since we are wrapping a function that does a single piece of work we should have used Single. With one item we are producing we don’t need to worry about back pressure.

Wrapping non RxJava code in early RxJava was a bit clunky. First you had to wrap the function:

Observable.just(expensiveFunction())

But that actually executes the function immediately. To avoid the expensiveFunction() being called immediately we often have to wrap it in defer:

Observable.defer(() -> {
    return Observable.just(expensiveFunction())
})

Fortunately in version 1.0.15 fromCallable was added that made this much easier.

Single.fromCallable(this::expensiveFunction);

Defer is the safe way of not accidentally calling expensive function before the subscription takes place. Kudos to Ryan Harter for pointing the RxJava v1 options out on his blog

Now let’s take a look at an asynchronous RxJava v2 example. First we need to create an Emitter. The Emitter takes a single subscribe:

Let’s say that our asynchronous method is the traditional callback pattern.

We have our interface for being notified that work is done:

interface ExpensiveFunctionCallback {
   fun onResult(result: Int)
}

We have a method that takes a callback that it will use when the work is done.

fun expensiveFunction(callback: ExpensiveFunctionCallback) {
   // saves a reference to the callback
   // often kicks off work elsewhere such as another thread
   // returns immediately
   // at some point work is completed and the callback is used
}

To convert this to a Single let’s start by using the create method. Then we create an instance of our callback. Our call back needs to emit the result. Since it’s a single we do that via the onSuccess method call. Lastly we need to actually kick off the work.

To do that we just need to call the expensiveFunction with our callback. Our callback acts as the bridge between the traditional callback style and Rx.

       Single.create<Int>{ emitter ->
           val callback = object : ExpensiveFunctionCallback{
               override fun onResult(result: Int) {
                    emitter.onSuccess(result)
               }

           }
           expensiveFunction(callback)
       }

Now for the RxJava v1 example. First we need to create an Emitter. The Emitter takes an Action. That action has a call function that gets called when it is subscribed to.

       Single.fromEmitter(Action1<SingleEmitter<Int>> { emitter ->
           val callback = object : ExpensiveFunctionCallback {
               override fun onResult(value: Int) {
                   emitter.onSuccess(value)
               }
           }

           expensiveFunction(callback)
       })

RxJava also has subjects. Subjects are Producers and Consumers.

You can think of them like pipes. You can put items in one side and get them on the other. This allows you to also bridge the gap between non Rx-APIs.

Subjects still have onError and onComplete. If you are ever in a situation where you want a Subject that should never end. Check out RxRelay by Jake Wharton.

A word of caution about subjects. The OnNext method is meant to be called from the same thread every time. It’s very easy to violate this expectation. Subjects are generally frowned upon as new Rx Devs tend to run towards them as the solution to everything in Rx.

Wait! Don't miss out.  Take this 9,586 word must have RxJava guide for Android Developers with you. Get it here:

Chapter 13

Time Traveling with RxJava

pasted image 0 15

If [unit tests] don’t run fast, they aren’t unit tests. – Michael Feathers, in Working Effectively With Legacy Code

There could not be a truer statement. Slow tests are useless because developers start avoiding running them. If tests are not run often, they are not serving to ensure that the code works as expected. If you do not have a test to prove it works as expected it does not.

RxJava has lots of useful operators. Some of them involve time. To verify that the Rx code you’ve created works as it’s expected we’d naturally want to write unit tests. If we have code that is supposed to execute in five minutes we’d waste a lot of time testing.

Let’s take a look at that exact use case in RxJava v2:

Observable.timer(5, TimeUnit.MINUTES)

Normally we’d create a TestObserver and subscribe.

TestObserver<Long> observer = new TestObserver<Long>()
Observable.timer(5, TimeUnit.MINUTES).subscribe(observer)

In v2 there is a helpful test method that will return the Test Observer:

val observer = Observable.timer(5, TimeUnit.MINUTES).test()

According to the docs we should receive a 0L when the time reaches 5 minutes. Let’s go ahead and verify that we received:

val observer = Observable.timer(5, TimeUnit.MINUTES).test()
observer.assertValue(0L)

Of course running this we’d discover that this fails. The next logical thing we could do is test if we completed.

val observer = Observable.timer(5, TimeUnit.MINUTES).test()
observer.assertComplete()

This would also fail. The reason this fails is because we aren’t waiting the five minutes for this to complete.

We could write the following:

Observable.timer(5, TimeUnit.MINUTES).subscribe(observer);
try {
   observer.await();
} catch (InterruptedException e) {
   e.printStackTrace();
}
observer.assertValue(0L);

This would work. Unfortunately this test will take 5 minutes. This is where TestScheduler comes in handy. Test scheduler allows you to advance time.

First create the scheduler:

TestScheduler scheduler = new TestScheduler();

Then do the other setup:

TestObserver<Long> observer = new TestObserver<Long>();

Note we specified the scheduler to use.

Observable.timer(5, TimeUnit.MINUTES, scheduler).subscribe(observer);

Next we will advance time

scheduler.advanceTimeBy(5, TimeUnit.MINUTES);

Then we do the final check

observer.assertValue(0L);

Awesome. We just tested a piece of code  that would have taken 5 minutes in seconds.

I’d like to point out that there are lots of very useful assert options in TestObserver and TestSubscriber. Maybe you are expecting an error(assertError), maybe you want to assert that it didn’t complete (assertNotComplete).

You might have noticed that we had to pass in the scheduler. That can be rather annoying as you’d have to make all of your code accept variables containing the schedulers to make it behave differently in production versus testing. Fortunately you can override the schedulers.

Essentially it looks like this:

RxJavaPlugins.setIoSchedulerHandler(scheduler -> testScheduler)

This line replaces the standard IOScheduler with the test scheduler. Warning you should call RxJavaPlugins.reset() to go back to defaults after every test. This is to prevent your scheduler changes from being applied to other tests that aren’t expecting it(thus causing failing tests). Andres Almiray has done a nice post about this here.

Chapter 14

Must Have Libraries

pasted image 0 14

I will now cover the libraries that I think are important. To start with Rx Lifecycle

RxLifecycle

The RxLifecycle Library provides an easy way to handle unsubscriptions in coordination with the Activity Lifecycle. Here is an example of Observable being set to unsubscribe during the OnDestroyMethod.

myObservable.compose(RxLifecycle.bindUntilEvent(lifecycle, ActivityEvent.DESTROY)).subscribe()

Kudos to Daniel Lew for his contributions to this library.

RxLint

Thanks to Hugo Visser and the rest of the Little Robots Team we have this super straightforward library. Remember when we discussed one of the common errors of not implementing onError?

I spoke about how your app will crash and it will have an Rx stack trace that doesn’t have anything to do with code you’ve written. Making difficult to figure out where the problem came from, especially if you have lots of Rx in your code base?

This library adds lint rules to prevent you from accidentally shooting yourself in the foot by not implementing onError.

pasted image 0 11

Retrofit

Of course we need to mention a networking library that supports Rx. Since Retrofit is a huge topic that could be a guide in and of itself we won’t go into much detail about it. Other than to

say that Retrofit allows you to nicely define an API contract in code that returns a Flowable, Observable, Single, Maybe, or Completable.

This is extremely useful as so much of our apps involve making Rest calls. Being able to take data from the internet and create plain old java objects and handle them in Rx is extremely useful. If you are using Kotlin the data class makes defining models a breeze. The benefits of Kotlin can easily be another guide in and of itself. So I’ll end it there.

RxBindings

RxBindings add Rx support to Android UI components. Instead of doing something like this:

Button submit = (Button)findViewById(R.id.submit); 
submit.setOnClickListener(new View.OnClickListener() {  
@Override public void onClick(View v) { // handle click } }); 

Using RxBinding, you can accomplish the same thing but with RxJava:

Button submit = (Button)findViewById(R.id.submit);  
Subscription sub = RxView.clicks(b).subscribe(new Action1Void() { @Override public void call(Void aVoid) { // handle click } }); 

// of course you should unsubscribe when appropriate

This may not appear like a big deal but it has a few major benefits:

  • Easily avoid memory leaks. Since it’s easy to unsubscribe/dispose at the correct time with Rx it helps that all of your UI callbacks have that useful feature. You don’t have to worry about accidentally holding onto a reference of a UI component and thus leak an Activity Context.
  • You can use the extensive arsenal of Rx operators to manipulate UI data and events
  • Consistent pattern for handling UI events, since everything becomes an Rx chain they can all be treated in a much more consistent way making it easier to mentally process.
  • Write more modular code. Sometimes when we write UI handling events we have to trigger more than one action that are distinct. Violating the single responsibility principle. With Rx we can multiple subscribers to say a button click and they are responsible for two totally different things helping keep logic separated.

Don Felker covers these in more detail here

RxKotlin

This one was so obvious that I forgot to include it. RxKotlin just provides some additional convenience methods. If you are developing in Kotlin use it, it makes life easier. Here is some sample code taken straight from the readme to illustrate the usefulness of this library:

import io.reactivex.rxkotlin.subscribeBy
import io.reactivex.rxkotlin.toObservable

fun main(args: Array<String>) {    
val list = listOf("Alpha", "Beta", "Gamma", "Delta", "Epsilon")    
list.toObservable() // extension function for Iterables            
        .filter { it.length >= 5 }            
        .subscribeBy(  // named arguments for lambda Subscribers                    
                onNext = { println(it) },                    
                onError =  { it.printStackTrace() },                    
                onComplete = { println("Done!") }            
         )}

pasted image 0 7

BEFORE YOU GO
Get this FREE additional chapter that will help you avoid RxJava beginner mistakes.

I'll show you the exact mistakes and solutions so that you can jumpstart your Rx Development such as:

  • Avoiding bugs due to concurrency configuration
  • Avoiding bugs with multiple subscriptions
  • Avoiding bugs due to error handling mistakes


I'll even throw in the full guide as a PDF.