RxJava Error Handling in Android

Wenn
Nerd For Tech
Published in
4 min readMay 28, 2021
Source: https://www.emojipng.com/preview/12037564

Error handling is one of essential requirements to build a robust android application. In this article, we will cover some error handling cases that will improve our code by using RxJava. RxJava library has been a mainstream library for composing asynchronous stream of events in android development. In android, we use RxJava extensively for API call to backend services in background threads, so blocking of main thread for long waiting API call can be avoided thanks to RxJava. RxJava also helps in avoiding callback hell by its stream chaining capability using flatmap , map and more operators.

Here’s the first user story to begin with, user can get his/her own profile data in the app and once data is fetched from API , the data should then be saved in the local storage of app. In tech implementation, we need to fetch user ID before calling API to fetch user’s data and save it in the end. Here’s the example of implementation:

By running the code above, it will produce this output:

Here’s the interesting case, what if we want to validate that user ID is not empty before calling the next API call. If user ID is not empty then we can proceed to next event to fetch user data, otherwise we need to show error message that indicates user ID is not valid. In first try, we might try to propagate error flag from one operator to the next operator by creating default value of response with error flag by using the approach below.

Here’s the output of first approach.

Using this approach does work in the end but it is very pain taking approach as we need to create default error object and always check error flag in the response just to continue the stream until onNext subscriber method to be invoked. It also abuses the usage of onNext as onNext should be treated as a success callback performed in a stream of events.

Now we learn that passing error flag in a stream of events is not a good practice and create a lot of repeated unnecessary validation in my opinion, so we should try different approach to just end the streams immediately when an error occurred in the streams. To end the series stream of events immediately , we should throw an exception. Wait… We should be aware that in android, throwing any exception during runtime will crash the app. Crashing the app is definitely not the way we wanted to handle this error correctly.

Hold on… Let’s be assured that RxJava handle exception events thrown in the middle of streams very well. It will encapsulate the exception then end the streams and finally execute onError callback in the subscription without crashing the app. Here’s the example:

Here’s the output:

By using this approach, The stream is stop immediately when an error occurred and error is handled properly in onError callback while onNext is implemented in the proper behaviour.

Now we have learned about throwing exception in the stream is encapsulated very well and onError callback is invoked when exception occurred. Let’s proceed to another interesting thing to check. What if exception occurred and onError is never been declared, what is expected to happen ?

Output:

OnErrorNotImplementedException is thrown from RxJava and will crash the app. As RxJava enforces that any exception happens in the stream, it should be handled on the subscription side. Other implementation other than implement the onError in the subscription side, is making use of onErrorReturnItem operator. onErrorReturnItem operator help us to construct default value when any exception occurred in the stream before passing down the stream. For examples:

Output:

So by using onErrorReturnItem operator, we may not implement onError callback in subscription side and avoid OnErrorNotImplementedException to occur as onError will never be invoked because of fallback default value is always provided in case any error happens thus streams will end up in onNext callback.

In the final use case , we will try different case of throwing exception in the streams as we realised that RxJava enforces that onError should be implemented in any use case of event streams. We are going to setup a use case to throw exception right after onComplete is invoked which means the stream should be ended and we will see what happens.

By executing the code above, RxJava throw exception again ! Which is not OnErrorNotImplementedException but UndeliverableException

It turns out that exceptions in RxJava doesn’t been swallowed even after the observable disposed/terminated, so RxJava will wrap this exception and continue to throw it and eventually crash the app. It’s been stated in the documentation.

Unfortunately, RxJava can’t tell which of these out-of-lifecycle, undeliverable exceptions should or shouldn’t crash your app. Identifying the source and reason for these exceptions can be tiresome, especially if they originate from a source and get routed to RxJavaPlugins.onError somewhere lower the chain.

Therefore, 2.0.6 introduces specific exception wrappers to help distinguish and track down what was happening the time of the error:

UndeliverableException: wraps the original exception that can't be delivered due to lifecycle restrictions on a Subscriber/Observer.

The only solutions for this is to setup a global RxJava error handle that will eventually catch these kinds of exceptions and handle it accordingly.

RxJavaPlugins.setErrorHandler(exception -> logger.log(exception));

That’s the end journey of discussion about exception handling in streams using RxJava Library. Thank you.

References:

Source Codes

--

--

Nerd For Tech
Nerd For Tech

Published in Nerd For Tech

NFT is an Educational Media House. Our mission is to bring the invaluable knowledge and experiences of experts from all over the world to the novice. To know more about us, visit https://www.nerdfortech.org/.

Wenn
Wenn

Written by Wenn

Google Certified Android Developer. Learning about Android, Backend technology and Algorithms.