Manejo de errores en RxJava

Al desarrollar una aplicación de Android, nos encontramos con muchos errores. Incluso una sola línea de código puede causar un error que puede arruinar todo el proyecto. Hay muchos tipos diferentes de errores y cada uno necesita una forma diferente de manejarlos, pero en este artículo, nos centraremos específicamente en el manejo de errores en RxJava. Entonces, antes de eso, entendamos algunas cosas importantes.

  • ¿Qué es un error?
  • ¿Qué es RxJava?

¿Qué es un error?

Los errores son problemas en un programa. Pueden entenderse como un error o una salida que se ejecutó pero no se esperaba esa salida. Pueden ocurrir errores debido a pequeños errores en el código. A veces, lo que sucede es que todo nuestro programa deja de ejecutarse debido a un pequeño error, pero queremos manejar ese error y dejar que nuestro programa se ejecute, por eso es necesario el manejo de errores.

¿Qué es RxJava?

RxJava es una biblioteca utilizada para la programación funcional reactiva como coroutines. Nos permite realizar tareas asincrónicas y ejecutar programas basados ​​en eventos utilizando secuencias observables. La dependencia para RxJava se da a continuación

 implementación ‘io.reactivex.rxjava3:rxandroid:3.0.0’

 implementación ‘io.reactivex.rxjava3:rxjava:3.0.0’

Veamos un código de ejemplo de RxJava ejecutándose exitosamente sin errores

En el siguiente código, se llama a la función onNext hasta que imprime todos los enteros y una vez que imprime todos los enteros, se llama a la función onComplete y el programa se ejecutó con éxito.

Kotlin

Observable.just(1, 2, 3, 4)
    .subscribe(object : Observer<Int> {
        override fun onComplete() {
            Log.d("onComplete ", "Completed")
        }
        override fun onSubscribe(d: Disposable) {
        }
        override fun onNext(t: Int) {
            Log.d("onNext ", t.toString())
        }
        override fun onError(e: Throwable) {
            Log.d("onError ", e.localizedMessage)
        }
    })

Producción: 

/onNext: 1
/onNext: 2
/onNext: 3
/onNext: 4
/onComplete: Completed

Ahora veamos un programa en el que lanzamos intencionalmente una excepción en una determinada condición.

En el código a continuación, lanzamos una excepción de puntero nulo cuando el número entero es 3. Tan pronto como obtenemos la excepción, no se llama a la función onNext y el código deja de ejecutarse o finaliza.

Kotlin

Observable.just(1,2,3,4).subscribe(object : Observer<Int> {
    override fun onComplete() {
        Log.d("onComplete ", "Completed")
    }
    override fun onSubscribe(d: Disposable) {
    }
    override fun onNext(i: Int) {
        if (i == 3) {
            throw NullPointerException("Its a Null Pointer Exception")
        }
        Log.d("onNext ", i.toString())
    }
    override fun onError(e: Throwable) {
        Log.d("onError ", e.localizedMessage)
    }
})

Producción:

Its a Null Pointer Exception

Manejo de errores en RxJava usando diferentes operadores de RxJava

En RxJava, los operadores son componentes que le permiten manipular los datos emitidos por Observables. A continuación se muestran los operadores en RxJava utilizados para el manejo de errores. Aprenderemos sobre cada uno de ellos.

  1. onExceptionResumeNext()
  2. onErrorResumeNext()
  3. hacerEnError()
  4. onErrorReturnItem()
  5. onErrorReturn()

1. onExceptionResumeNext() 

Si este operador obtiene una excepción incluso antes del inicio de onComplete, onError y onNext, irá directamente a onExceptionResumeNext y realizará la tarea dentro del alcance de onExceptionResumeNext(). Entendamos esto con más detalle con la ayuda del siguiente código.

Kotlin

Observable.just(1, 2, 3, 4)
    .subscribeOn(Schedulers.io())
    .observeOn(AndroidSchedulers.mainThread())
    .doOnNext {
        if (it == 2) {
            throw (RuntimeException("Exception on 2"))
        }
    }.onExceptionResumeNext {
        Log.d("onExceptionResumeNext : ","1")
    }
    .subscribe(object : Observer<Int> {
        override fun onComplete() {
            Log.d("onComplete ", "Completed")
        }
        override fun onSubscribe(d: Disposable) {
        }
        override fun onNext(i: Int) {
            Log.d("onNext : ", i.toString())
        }
        override fun onError(e: Throwable) {
            Log.d("onError", e.localizedMessage)
        }
    })

Producción: 

onNext : 1
onExceptionResumeNext : 1

Cuando se llama a OnNext() por primera vez e imprime 1 y cuando se devuelve el valor 2, se llama a onExceptionResumeNext y, por lo tanto, se ejecuta el código para imprimir 1 dentro.

2. OnErrorResumeNext()

Este operador maneja el arrojable generado por el programa. Echemos un vistazo al siguiente código.

Kotlin

Observable.just(1, 2, 3, 4)
    .subscribeOn(Schedulers.io())
    .observeOn(AndroidSchedulers.mainThread())
    .map { x ->
        if (x == 2) {
            throw NullPointerException("Its a NPE")
        }
        x * 10
    }.onErrorResumeNext { throwable: Throwable ->
        return@onErrorResumeNext ObservableSource {
            Log.d("onErrorResumeNext", throwable.localizedMessage)
        }
    }.subscribe(object : Observer<Int> {
        override fun onComplete() {
            Log.d("onComplete", "Completed")
        }
        override fun onSubscribe(d: Disposable) {
        }
        override fun onNext(i: Int) {
            Log.d("onNext", i.toString())
        }
        override fun onError(e: Throwable) {
            Log.d("onError", e.localizedMessage)
        }
    })

Producción: 

onNext: 10
onErrorResumeNext: Its a NPE

Cuando se llama a onNext e imprime el primer entero después de multiplicarlo por 10 en el operador de mapa y cuando aparece el valor 2, arroja la excepción NPE. No se moverá directamente a onError y el error se manejará en onErrorResumeNext y podemos realizar el resto de acciones en eso. 

3. hacerEnError()

El operador doOnError es algo único del resto de los operadores. Podemos llamarlo un operador de efecto secundario . En el caso de este operador, el usuario verá el error antes de que ocurra la excepción.

Kotlin

Observable.just(1, 2, 3, 4)
    .subscribeOn(Schedulers.io())
    .observeOn(AndroidSchedulers.mainThread())
    .doOnNext {
        if (it == 2) {
            throw (RuntimeException("Exception on 2"))
        }
    }
    .doOnError {
        Log.d("doOnError", "Exception Occurred")
    }.subscribe(object : Observer<Int> {
        override fun onComplete() {
            Log.d("onComplete", "Completed")
        }
        override fun onSubscribe(d: Disposable) {
        }
        override fun onNext(i: Int) {
            Log.d("onNext", i.toString())
        }
        override fun onError(e: Throwable) {
            Log.d("onError", e.localizedMessage)
        }
    })

Producción:

onNext: 1
doOnError: Exception Occurred
onError: Exception on 2

Int el resultado anterior, donde el primer 1 se imprime desde onNext y luego, cuando el valor llega a 2, se produce una excepción. Como llamamos a un operador de efectos secundarios , doOnError se llama primero antes que el método onError. Si no usamos un operador de efectos secundarios, se debería llamar al operador OnError. así que, en resumen, los operadores de efectos secundarios son aquellos que son llamados antes que los métodos principales como onNext(), onError().

4. onErrorReturnItem()

Este operador devuelve un elemento cada vez que se produce una excepción o un error, seguido del operador onComplete().

Kotlin

Observable.just(1, 2, 3, 4)
    .subscribeOn(Schedulers.io())
    .observeOn(AndroidSchedulers.mainThread())
    .doOnNext {
        if (it == 2) {
            throw (RuntimeException("Exception on 2"))
        }
    }
    .onErrorReturnItem(10)
    .subscribe(object : Observer<Int> {
        override fun onComplete() {
            Log.d("onComplete ", "Completed")
        }
        override fun onSubscribe(d: Disposable) {
        }
        override fun onNext(i: Int) {
            Log.d("onNext", i.toString())
        }
        override fun onError(e: Throwable) {
            Log.d("onError", e.localizedMessage)
        }
    })

Producción:

onNext: 1
onNext: 10
onComplete: Completed

Cuando se llama onNext() y se imprime el valor 1 y obtenemos una excepción cuando el valor se convierte en 2 en doOnNext(). Pero como estamos usando el operador onErrorReturnItem(), devolverá un elemento cuando se produzca la excepción del mismo tipo de datos. Aquí, como estamos usando el tipo de datos entero, devolverá un elemento de tipo de datos entero en el operador onNext(), y luego llamará al operador onComplete() por fin.

5. onErrorReturn()

A veces necesitamos generar un elemento predeterminado cada vez que se produce un error o una excepción. Por lo tanto, usamos onErrorReturn() que proporciona una lambda y un throwable para devolver. Veamos el código a continuación.

Kotlin

Observable.just(1, 2, 3, 4)
    .subscribeOn(Schedulers.io())
    .observeOn(AndroidSchedulers.mainThread())
    .doOnNext {
        if (it == 2) {
            throw (RuntimeException("Exception on 2"))
        }
    }
    .onErrorReturn { t: Throwable ->
        Log.d("onComplete", t.localizedMessage)
        5
    }.subscribe(object : Observer<Int> {
        override fun onComplete() {
            Log.d("onComplete", "Completed")
        }
        override fun onSubscribe(d: Disposable) {
        }
        override fun onNext(i: Int) {
            Log.d("onNext", i.toString())
        }
        override fun onError(e: Throwable) {
            Log.d("onError", e.localizedMessage)
        }
    })

Producción:

onComplete: Exception on 2
onNext: 5
onComplete: Completed

Se llama a onNext e imprime 5 después de detectar la excepción y luego completa el flujo. Podemos ver que hemos pasado el valor 5 en el operador onErrorReturn. Si no pasamos un valor, obtendremos un valor predeterminado.

De esta manera podemos manejar errores, particularmente en RxJava.

Publicación traducida automáticamente

Artículo escrito por shekharshinde9990 y traducido por Barcelona Geeks. The original can be accessed here. Licence: CCBY-SA

Deja una respuesta

Tu dirección de correo electrónico no será publicada. Los campos obligatorios están marcados con *