J'utilise des coroutines kotlin pour la demande de réseau en utilisant la méthode d'extension pour appeler la classe en retrofit comme ceci
public suspend fun <T : Any> Call<T>.await(): T {
return suspendCancellableCoroutine { continuation ->
enqueue(object : Callback<T> {
override fun onResponse(call: Call<T>?, response: Response<T?>) {
if (response.isSuccessful) {
val body = response.body()
if (body == null) {
continuation.resumeWithException(
NullPointerException("Response body is null")
)
} else {
continuation.resume(body)
}
} else {
continuation.resumeWithException(HttpException(response))
}
}
override fun onFailure(call: Call<T>, t: Throwable) {
// Don't bother with resuming the continuation if it is already cancelled.
if (continuation.isCancelled) return
continuation.resumeWithException(t)
}
})
registerOnCompletion(continuation)
}
}
puis du côté appelant j'utilise la méthode ci-dessus comme celle-ci
private fun getArticles() = launch(UI) {
loading.value = true
try {
val networkResult = api.getArticle().await()
articles.value = networkResult
}catch (e: Throwable){
e.printStackTrace()
message.value = e.message
}finally {
loading.value = false
}
}
je veux réessayer exponentiellement cet appel api dans certains cas, c'est-à-dire (IOException) comment puis-je y arriver ??
Je suggérerais d'écrire une aide fonction d'ordre supérieur pour votre logique de nouvelle tentative. Vous pouvez utiliser l'implémentation suivante pour commencer:
suspend fun <T> retryIO(
times: Int = Int.MAX_VALUE,
initialDelay: Long = 100, // 0.1 second
maxDelay: Long = 1000, // 1 second
factor: Double = 2.0,
block: suspend () -> T): T
{
var currentDelay = initialDelay
repeat(times - 1) {
try {
return block()
} catch (e: IOException) {
// you can log an error here and/or make a more finer-grained
// analysis of the cause to see if retry is needed
}
delay(currentDelay)
currentDelay = (currentDelay * factor).toLong().coerceAtMost(maxDelay)
}
return block() // last attempt
}
L'utilisation de cette fonction est très simple:
val networkResult = retryIO { api.getArticle().await() }
Vous pouvez modifier les paramètres de nouvelle tentative au cas par cas, par exemple:
val networkResult = retryIO(times = 3) { api.doSomething().await() }
Vous pouvez également modifier complètement l'implémentation de retryIO
pour l'adapter aux besoins de votre application. Par exemple, vous pouvez coder en dur tous les paramètres de nouvelle tentative, vous débarrasser de la limite du nombre de nouvelles tentatives, modifier les valeurs par défaut, etc.