es.davy.ai

Preguntas y respuestas de programación confiables

¿Tienes una pregunta?

Si tienes alguna pregunta, puedes hacerla a continuación o ingresar lo que estás buscando.

Mejora el encadenamiento de múltiples (tres) Completables utilizando RxJava

Quiero invocar un Completable después de otro. Es decir, cuando el primero termine, invocar el segundo y cuando el segundo termine, invocar el tercero. Ya he intentado diferentes cosas como andThen(), pero descubrí que no “espera” a que el Completable anterior termine, ya que se ejecuta en paralelo. Hasta ahora, esto es lo que he encontrado y funciona como quiero, pero ¿hay alguna forma mejor de mejorar esto? ¿Hay alguna función de operación o algo para deshacerse de Completable.defer en cada etapa?

Aquí hay un ejemplo que hasta ahora funciona:

private fun invokeAllThreeDoSomeLogic() {
disposable.add(Completable.concatArray(
    Completable.defer {
        firstApi.getData().doOnError { t: Throwable? ->
            Timber.w(
                t,
                "primer error"
            )
        }
    },
    Completable.defer {
        Completable.fromObservable(secondApi.getData()
            .doOnError { t: Throwable? ->
                Timber.i(
                    t,
                    "Segundo error"
                )
            }
    },
    Completable.defer {
        thirdApi.refresh().doOnError { t: Throwable? ->
            Timber.i(
                t,
                "Tercer error"
            )
        }
    }
).subscribe(
    { },
    { t: Throwable? ->
        Timber.w(t, "algo salió mal")
    })
)
}
Tags:  , ,

Answer

  1. Avatar for davy.ai

    Para invocar un Completable después de otro, puedes usar el operador andThen en RxJava. Sin embargo, como mencionaste, este no espera a que el Completable anterior termine y se ejecuta en paralelo.

    Una solución a esto es usar Completable.defer en cada etapa para asegurar que el Completable anterior haya terminado antes de invocar el siguiente. Si bien esto funciona, se puede mejorar en cuanto a legibilidad y mantenibilidad.

    Una forma de mejorar esto es usar el operador concatWith en lugar de concatArray. Esto te permite encadenar Completables de una manera más legible, sin la necesidad de Completable.defer en cada etapa.

    Aquí tienes un ejemplo de cómo usar concatWith:

    private fun invokeAllThreeDoSomeLogic() {
    
        val firstCompletion = firstApi.getData()
            .doOnError { t: Throwable? ->
                Timber.w(t, "primer error")
            }
    
        val secondCompletion = secondApi.getData()
            .doOnError { t: Throwable? ->
                Timber.i(t, "Segundo error")
            }
    
        val thirdCompletion = thirdApi.refresh()
            .doOnError { t: Throwable? ->
                Timber.i(t, "Tercer error")
            }
    
        disposable.add(firstCompletion
            .concatWith(secondCompletion)
            .concatWith(thirdCompletion)
            .subscribe(
                {},
                { t: Throwable? ->
                    Timber.w(t, "algo salió mal")
                })
        )
    }
    

    Al encadenar los Completables con concatWith, el Completable anterior terminará antes de invocar el siguiente, sin necesidad de Completable.defer. Esto hace que el código sea más legible y fácil de mantener.

Comments are closed.