Search code examples
androidkotlinretrofitrx-java

Chain Completable and a Single RxJava + Retrofit


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.


Solution

  • Use andThen

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