Generalidades

Kotlin Flow Retry y RetryWhen Extension Functions | Via SagaRock101 | Agosto de 2021

Roca legendaria 101

En este artículo, escribiré un artículo sobre reintentar llamadas de red usando extensiones de transmisión de Kotlin

1*rXAe G QpjwQl4sDVwPqmQ

Porqué necesitamos esto

En el caso

  • Falló la autenticación del token
  • Red incierta

¿Qué es el tráfico?

  • Es un flujo de datos desde el flujo ascendente (entrada) al flujo descendente (salida), que se puede calcular de forma asincrónica.
  • En este caso, el flujo ascendente es la respuesta de la red y el flujo descendente es donde mostramos la respuesta en la interfaz de usuario (actividad / fragmento)

¿Qué es una corrutina?

Son hilos ligeros.

¿Qué es la función de pausa?

Estas son funciones que pueden realizar tareas de larga duración y esperar a que se complete sin bloquear

Necesito confiar en

Para Kotlin coroutine android

Rever

voluntad Dé un ejemplo simple para mostrar cómo podemos reintentar una tarea normal de larga ejecución. Más adelante se proporcionará un ejemplo para ilustrar cómo podemos usar esta función para reintentar una llamada a la API usando la arquitectura MVVM

fun startTask(): Flow<Int> 
return flow 
for (i in 1..4) 
val randomInt = (0..2).random()
if (randomInt == 0) 
throw IndexOutOfBoundsException()
 else if (randomInt == 2) 
throw  IOException()

emit(i)

.flowOn(Dispatchers.IO)
suspend fun main(args: Array<String>)     startTask()
.retry(3) 
println("retrying...")
delay(2000)
it is IndexOutOfBoundsException
.catch 
print(it.toString())

.collect 
println(it)
  • Esta Rever() Acepta un parámetro opcional de tipo Long, que representa el número de veces que se reintenta el flujo ascendente hasta que se produce una excepción en el flujo ascendente.Si no se proporciona, se utilizará el valor Long.MAX_VALUE predeterminado
  • Una función de suspensión con throwable como parámetro y tipo de retorno booleano (si no se proporciona) usará el valor predeterminado verdadero
  • Esta captura() Capture la excepción en el flujo ascendente y llame a la acción especificada
  • ya que Rever() Es una función de suspensión. Podemos introducir un retraso entre las llamadas de reintento para obtener algo de tiempo de búfer con la ayuda de Retraso (tiempo milisegundos: largo) Esta es también una función de suspensión.
retrying...
retrying...
retrying...
1
java.io.IOException
Process finished with exit code 0
public fun <T> Flow<T>.retry(
retries: Long = Long.MAX_VALUE,
predicate: suspend (cause: Throwable) -> Boolean =  true 
): Flow<T> 
require(retries > 0)  "Expected positive amount of retries, but had $retries" 
return retryWhen  cause, attempt -> attempt < retries && predicate(cause) 

println("retrying...")
delay(2000)
it is IndexOutOfBoundsException
startTask()
.retryWhen .catch 
print(it.toString())

.collect 
println(it)
retrying...
1
retrying...
retrying...
retrying...
java.lang.IndexOutOfBoundsException
attempt < 3
public fun <T> Flow<T>.retryWhen(predicate: suspend FlowCollector<T>.(cause: Throwable, attempt: Long) -> Boolean): Flow<T> =
flow 
var attempt = 0L
var shallRetry: Boolean
do 
shallRetry = false
val cause = catchImpl(this)
if (cause != null) 
if (predicate(cause, attempt)) 
shallRetry = true
attempt++
 else 
throw cause


 while (shallRetry)
  • El motivo es que se produjo una excepción en el flujo ascendente
  • Los intentos son el número de intentos de reintentar el flujo ascendente
  • Esta función devuelve la secuencia a la corriente descendente
  • Probó una variable interna que se incrementará dentro del ciclo do-while
  • Tiene shouldRetry, que también es una variable interna y una bandera booleana, lo que permite que el bucle se ejecute hasta que la función lambda devuelva falso (como Predicado (razonar, intentar))
  • catchImp () Reciba la función de la interfaz FlowCollector. Verifique y devuelva excepciones o nulos desde el origen.
  • Al comprobar el flujo de aguas arriba anormal catchImp () cada vez Utilice la función de suspensión de recopilación de la interfaz de flujo para activar internamente el flujo ascendente.
 cause is IOException

if (predicate(cause, attempt)) 
shallRetry = true
attempt++
 else 
throw cause
@GET("top-headlines")
suspend fun getTopHeadlines(
@Query("country") country: String
): TopHeadlines
suspend fun getNewsHeadLines(country: String): Flow<TopHeadlines> 
return flow 
emit(newsHeadlinesService.getTopHeadlines(country))
.flowOn(Dispatchers.IO)
fun getNewsHeadlines(country: String): LiveData<DataWrapper<TopHeadlines>> 
return liveData 
emit(DataWrapper.loading(null))
remoteSource.getNewsHeadLines(country).retry(3) 
delay(NETWORK_RETRY_DELAY)
return@retry true
.catch 
emit(DataWrapper.error(it.message.toString()))
.collect 
emit(DataWrapper.success(it))


val newsHeadLinesLD = newsHeadLinesMLD.switchMap 
if (it.category.isEmpty())
newsHeadlinesRepo.getNewsHeadlines(it.country)
else 
newsHeadlinesRepo.getNewsHeadlines(it.country, it.category)

viewModel.newsHeadLinesLD.observe(viewLifecycleOwner, Observer {
when (it.status) 
DataWrapper.Status.LOADING -> 
DataWrapper.Status.SUCCESS -> 
DataWrapper.Status.ERROR -> 
)

LEER  Comunicación Google Pixel 6.Después de meses de revelación, Google ... | Jerry | Agosto de 2021

Publicaciones relacionadas

Deja una respuesta

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

Botón volver arriba