Search code examples
androidkotlinrx-java2

Chaining Calls on RxJava


There are cases when I need to chain RxJava calls.

The simplest one:

ViewModel:

fun onResetPassword(email: String) {
    ...
    val subscription = mTokenRepository.resetPassword(email)
        .observeOn(AndroidSchedulers.mainThread())
        .subscribeOn(Schedulers.io())
        .subscribe(
            //UI update calls
        )
    ...
}

My Repository:

fun resetPassword(email: String): Single<ResetPassword> {
        return Single.create { emitter ->

            val subscription = mSomeApiInterface.resetPassword(email)
                .observeOn(AndroidSchedulers.mainThread())
                .subscribeOn(Schedulers.io())
                .subscribe({
                    emitter.onSuccess(...)
                }, { throwable ->
                    emitter.onError(throwable)
                })

            ...

        }
    }

My Question

Do I need to Add:

.observeOn(AndroidSchedulers.mainThread())
.subscribeOn(Schedulers.io())

for both calls to avoid any app freeze? or the second one for API call is enough?


Solution

  • No, you don't need to add

    .observeOn(AndroidSchedulers.mainThread())
    .subscribeOn(Schedulers.io())
    

    for the repo and the viewmodel.

    .observeOn usually should be called right before handling the ui rendering. So usually, you'll need it in the ViewModel right before updating the ui or emitting the LiveData values.

    Also, you properly don't need to subscribe to mSomeApiInterface in your repo, I think it would be better off to just return in as it's from your method up the chain, somthing like this:

    fun resetPassword(email: String): Single<ResetPassword> {
            return mSomeApiInterface.resetPassword(email);
        }
    

    and if you have any mapping needed you can chain it normally

    fun resetPassword(email: String): Single<ResetPassword> {
            return mSomeApiInterface.resetPassword(email)
                    .map{it -> }
        }
    

    This way you can write your ViewModel code as follow

    fun onResetPassword(email: String) {
        ...
        // note the switcing between subscribeOn and observeOn
        // the switching is in short: subscribeOn affects the upstream,
        // while observeOn affects the downstream.
        // So we want to do the work on IO thread, then deliver results
        // back to the mainThread.
        val subscription = mTokenRepository.resetPassword(email)
            .subscribeOn(Schedulers.io())
            .observeOn(AndroidSchedulers.mainThread())
            .subscribe(
                //UI update calls
            )
        ...
    }
    

    This will run the API request on the io thread, will returning the result on the mainThread, which is probably what you want. :)

    This artical has some good examples and explanations for subscribeOn and observeOn, I strongly recommend checking it.