Using HandlerScheduler from RxAndroid
Working in different threads in android became more easily in RxJava. Developers using RxJava don’t need to worry (in most cases) about thread executions in background or parallel. Simply put a magical subscribeOn and observeOn(AndroidSchedulers.mainThread()) and everything works fine. But there is the HandlerScheduler in RxAndroid, so… how and when do I need use it?
What this article is about?
In this article I will show how to manage RxJava calls using HandlerScheduler by RxAndroid. The main point is explain how the threading process works in Android in a simple way and show a simple implementation of customized threading execution.
Let’s talk about Handlers
Handlers has a wide use in android since you can delay executions specially when you need to update the state of your view periodically. By default, creating a simple handler in a Activity or Fragment you just delay the execution of your code within the MainThread Looper, this means that you cannot perform large or network operations in this Handler, otherwise you will get a Exception, like NetworkOnMainThreadException.
The MainThread has a continuous loop (MainLooper) waiting for some operation be executed. Imagine a revolving door in a bank and expect to transport just 1 people at the time — It’s just waiting for someone to step in to delivery inside the building, and pick up the next person. Loopers actually do this job and, because of this, you cannot perform long or blocking operations in this loop, otherwise the UI will not have a change to be executed since it will need to wait until the looper became available and the application will freeze to the user. It’s just like someone sleeps inside the revolving door when you are the next to get in.
If you want to perform background operations in this way, you need to create a Handler from a new looper attached to some HandlerThread.
Creating your own Handler with Looper
The example below is a example of a Handler that uses a separated looper:
We extend the Handler class and set the looper from a new HandlerThread. Also, we return the Looper after the HandlerThread call onLooperPrepared(), so we use a Semaphore here.
Now we can perform a safe background call in RxJava like this:
Quite easy, huh? Check the debugger to see the current thread:
Be careful by using HandlerSchedulers.from(new Handler())
What if you subscribe using a HandlerScheduler.from(new Handler())? Check this example:
Call this code will execute the observable in the current thread. So, if you are creating this Observable inside the MainThread, it will be executed in the MainThread.
By default, a new Handler is attached to the current Looper. If you try to create a new Handler in some arbitrary thread that doesn't have a Looper, you will get this exception:
java.lang.RuntimeException: Can’t create handler inside thread that has not called Looper.prepare()
That's why I've created the CustomHandler class to ensure that I always have a Looper prepared.
When I need to use?
- If you don't want to use the Schedulers from RxJava, you can create your own HandlerThread to perform background operations.
- If you are working with a third-party library that, internally, creates a new Handler and you want to make this library to work with RxJava using background threads.
Last week I created an app using the Oracle Mobile Cloud Service, and this library creates Handlers in a lot of internal methods, so in this case I always use the library with a HandlerThread to ensure that all internal Handlers will be created and I can perform all the calls in background thread. Something like this:
Doing this, I’m able to work asynchronously with MCS.
It's quite simple to use HandlerScheduler from RxAndroid. Just remember to always prepare the Looper from the Handler that you are using, otherwise you can get in trouble. Also, it will be a good choice if you need to integrate with libraries that need a Looper to be executed (e.g. instantiate Handlers internally).
Happy coding =)