RxJava allow a different approach of programming than imperative approach. It is reactive based, where codes are not activate until it knows it’s end mean (subscribed to).
Check out a simple analogy example in my previous blog
https://medium.com/@elye.project/rxjava-analogy-with-3-line-kotlin-codes-dd5b79cde4ce
Here, I will share the benefits compare to imperative approach.
Using imperative approach, moving a piece of code to background thread is hard work. However in RxJava, we could easily define what thread each part of the chain would be in.
Use subscribeOn()
to define the default thread the entire RxJava chain work on.
Use observerOn()
to define what the bottom chain thread will be work on.
E.g. the below show the default Thread is on Schedulers.io()
while the displayResult()
is on AndroidManifest.mainThread()
.
Observable.create(ObservableOnSubscribe<String>
{ emitter -> emitter.onNext(fetchFromServer()) })
.subscribeOn(Schedulers.io())
.observeOn(AndroidSchedulers.mainThread())
.subscribe{ result -> displayResult(result) }
In the imperative world, imaging you call a function fetch from server, that could potential result in error. So you need to catch and report the error, and has also need callback to state that to the caller.
Also if you have some in between operation, that could result in Error, you need to handle that as well. Hence error handling could be all over the places. Or you have crazy callbacks to handle that.
In RxJava, you could just report the Error, and the subscriber would just be able to centralize how it want to process them.
E.g. the below show the Error could be during fetchFromServer or processResult. But it is centralized in the subscriber managing the error e.g. Log.e the error message
Observable.create(ObservableOnSubscribe<String>
{ emitter ->
try {
emitter.onNext(fetchFromServer())
emitter.onComplete()
} catch (error: Exception) {
emitter.onError(error)
}
})
.map { result ->
try {
processResult(result)
} catch (error: Exception) {
throw OutOfMemoryError("Process Running out of Memory")
}
}
.subscribe(
{ result -> displayResult(result) },
{ error -> Log.e("TAG", "{$error.message}")},
{ Log.d("TAG", "completed") }
)
Also, if the error happens during fetchFromServer, it will skip the operators, and let the Subscriber handle it directly.
Beside, other than Error, it also has onComplete support, that one could indicate the emitting process is completed