Home > Back-end >  Chain Completable and a Single RxJava Retrofit
Chain Completable and a Single RxJava Retrofit

Time:05-19

In My repository, I have two API calls that should be done sequentially.

  1. First API call returns Completable -> If this API call fails, we should not proceed further, if it succeeds we should continue with the second API call
  2. Second API call returns Single -> If this API call fails, we should NOT throw an error and we can still continue

How can I achieve this?

What I am doing now is using separate calls from repo.

Repository:

override fun activate(id: String): Completable {
    return api1.post(Body(id = id))
        .subscribeOn(schedulerProvider.io())
}

override fun fetchAd(id: String): Single<SummaryAd> {
    return api2.getAd(adId)
        .subscribeOn(schedulerProvider.io())
        .map { it.toSummaryAd() }
}

ViewModel:

private fun activate(id: String) {
    repository.activate(id)
        .subscribeOn(schedulerProvider.io())
        .observeOn(schedulerProvider.ui())
        .subscribe(
            { // if it is successful, let's continue
                fetchAd(id)
            },
            { // otherwise fail
                _state.value = State.ErrorActivation
            }
        ).also { compositeDisposable.add(it) }
}

private fun fetchAd(id: String) {
    repo.fetchAd(id)
        .subscribeOn(schedulerProvider.io())
        .observeOn(schedulerProvider.ui())
        .subscribe(
            { // success
                _state.value = State.ActivationSuccess(it)
            },
            {
                // even though the call has failed, the activation is succeeded, so we still can proceed but with empty data
                _state.value = State.ActivationSuccess(SummaryAd())
            }
        ).also { compositeDisposable.add(it) }
}

Basically what I want ultimately is to have a single function in my viewModel and let the repository sequentially call them and only throw error If the first API call failed.

CodePudding user response:

Use andThen

activate(id)
.andThen(
    fetchAd(id)
    .onErrorReturnItem(SummaryAd())
)

CodePudding user response:

This is roughly what you need, depending on your implementation of _state you might also not need to set its value on UI thread.

 compositeDisposable.add(
            repository.activate(id)
                .subscribeOn(schedulerProvider.io())
                .andThen{
                    repo.fetchAd(id)
                        .subscribeOn(Schedulers.io())
                        .onErrorReturnItem { SummaryAd() }
                }
                .observeOn(schedulerProvider.ui())
                .subscribe(
                    {
                        _state.value = State.ActivationSuccess(it)
                    },
                    {
                        // this will be executed only, in case of activate request failure, as fetch add can never fail due to one rrorReturn
                        _state.value = State.ErrorActivation
                    }
                )
        )
  • Related