7

Hi I have a rxjava flat map in which I want to call a coroutine usecase onStandUseCase which is an api call

Initially the use case was also rxjava based and it used to return Observable<GenericResponse> and it worked fine now that I changed the use to be coroutines based it only returns GenericResponse

how can modify the flatmap to work fine with coroutines use case please

        subscriptions += view.startFuellingObservable
        .onBackpressureLatest()
        .doOnNext { view.showLoader(false) }
        .flatMap {
            if (!hasOpenInopIncidents()) {
                //THIS IS WHERE THE ERROR IS IT RETURNS GENERICRESPONSE
                onStandUseCase(OnStandUseCase.Params("1", "2", TimestampedAction("1", "2", DateTime.now()))) {
                    
                }
               
            } else {
                val incidentOpenResponse = GenericResponse(false)
                incidentOpenResponse.error = OPEN_INCIDENTS
                Observable.just(incidentOpenResponse)
            }
        }
        .subscribe(
            { handleStartFuellingClicked(view, it) },
            { onStartFuellingError(view) }
        )

OnStandUseCase.kt

class OnStandUseCase @Inject constructor(
    private val orderRepository: OrderRepository,
    private val serviceOrderTypeProvider: ServiceOrderTypeProvider
) : UseCaseCoroutine<GenericResponse, OnStandUseCase.Params>() {

    override suspend fun run(params: Params) = orderRepository.notifyOnStand(
        serviceOrderTypeProvider.apiPathFor(params.serviceType),
        params.id,
        params.action
    )

    data class Params(val serviceType: String, val id: String, val action: TimestampedAction)
}

UseCaseCoroutine

abstract class UseCaseCoroutine<out Type, in Params> where Type : Any {

    abstract suspend fun run(params: Params): Type

    operator fun invoke(params: Params, onResult: (type: Type) -> Unit = {}) {
        val job = GlobalScope.async(Dispatchers.IO) { run(params) }
        GlobalScope.launch(Dispatchers.Main) { onResult(job.await()) }
    }
}

startFuellingObservable is

val startFuellingObservable: Observable<Void>

Here is the image of the error

enter image description here

Any suggestion on how to fix this please

thanks in advance R

BRDroid
  • 3,920
  • 8
  • 65
  • 143
  • Use the [integration library](https://github.com/Kotlin/kotlinx.coroutines/tree/master/reactive/kotlinx-coroutines-rx2). Then write `rxSingle { ... }.toObservable()`. And since you don't need observables, you can write `concatMapSingle` instead of `flatMap`. – George Leung Jan 08 '21 at 05:56
  • Hello @GeorgeLeung a startFuellingObservable will still be an observable, I dont want to change tthat side – BRDroid Jan 08 '21 at 18:03
  • [`Observable#concatMapSingle`](http://reactivex.io/RxJava/javadoc/io/reactivex/Observable.html#concatMapSingle-io.reactivex.functions.Function-) `return`s an `Observable`. By "don't need observables", what I meant was that a suspend function corresponds to a `Single` instead of an `Observable`. – George Leung Jan 08 '21 at 18:25
  • can you please suggest how my code needs to be changed please, I am pretty new to this – BRDroid Jan 08 '21 at 18:42

1 Answers1

5

There is the integration library linking RxJava and Kotlin coroutines.

rxSingle can be used to turn a suspend function into a Single. OP wants an Observable, so we can call toObservable() for the conversion.

.flatMap {
    if (!hasOpenInopIncidents()) {
        rxSingle {
            callYourSuspendFunction()
        }.toObservable()
    } else {
        val incidentOpenResponse = GenericResponse(false)
        incidentOpenResponse.error = OPEN_INCIDENTS
        Observable.just(incidentOpenResponse)
    }
}

Note that the Observables in both branches contain just one element. We can make this fact more obvious by using Observable#concatMapSingle.

.concatMapSingle {
    if (!hasOpenInopIncidents()) {
        rxSingle { callYourSuspendFunction() }
    } else {
        val incidentOpenResponse = GenericResponse(false)
        incidentOpenResponse.error = OPEN_INCIDENTS
        Single.just(incidentOpenResponse)
    }
}
George Leung
  • 1,209
  • 1
  • 7
  • 11