withTimeout e withTimeoutOrNull
Limiti il tempo di esecuzione con wrapper di timeout e gestisca TimeoutCancellationException.
withTimeout e withTimeoutOrNull è una lezione Kotlin Academy gratuita su CoddyKit. Questa è la lezione 2 di 4. Puoi leggere la lezione completa qui gratuitamente — poi esercitati direttamente nel browser con un editor di codice integrato e un tutor IA disponibile 24/7. Fa parte del percorso di apprendimento Kotlin Academy, e i tuoi progressi si sincronizzano tra il web e l'app CoddyKit. Il corso Kotlin Academy include 4 lezioni in totale.
Perché utilizzare i timeout
Le coroutine possono rimanere bloccate indefinitamente durante operazioni di rete o di I/O. withTimeout annulla il blocco se non viene completato entro il numero di millisecondi specificato.
import kotlinx.coroutines.*
fun main() = runBlocking {
try {
withTimeout(200) {
delay(1000) // simulates slow network
println("This never prints")
}
} catch (e: TimeoutCancellationException) {
println("Timed out!")
}
}Nozioni di base su withTimeout
withTimeout(millis) { ... } genera TimeoutCancellationException (una sottoclasse di CancellationException) se il blocco supera il limite.
import kotlinx.coroutines.*
suspend fun fetchData(): String {
delay(100)
return "data"
}
fun main() = runBlocking {
val result = withTimeout(500) {
fetchData()
}
println(result) // data
}withTimeoutOrNull
withTimeoutOrNull restituisce null in caso di timeout invece di generare un'eccezione, facilitando la gestione dei timeout come normale flusso di esecuzione.
import kotlinx.coroutines.*
fun main() = runBlocking {
val result: String? = withTimeoutOrNull(200) {
delay(1000)
"done"
}
println(result ?: "Timeout — using default")
}Timeout con valore restituito
In caso di successo, entrambe le funzioni restituiscono il valore dell'ultima espressione nel blocco.
import kotlinx.coroutines.*
fun main() = runBlocking {
val response = withTimeoutOrNull(500) {
delay(100)
mapOf("status" to 200, "body" to "OK")
}
println(response?.get("status")) // 200
}Annidamento dei timeout
I timeout interni scadono per primi. Il timeout esterno scatta solo se quello interno non annulla l'esecuzione per primo: è utile per distinguere i timeout per richiesta da quelli globali.
import kotlinx.coroutines.*
fun main() = runBlocking {
withTimeoutOrNull(1000) { // global
withTimeoutOrNull(200) { // per-call
delay(300)
println("inner done") // won't print
} ?: println("Inner timed out")
delay(100)
println("outer still running")
}
}TimeoutCancellationException
TimeoutCancellationException è una CancellationException, quindi viene trattata come una normale cancellazione dal meccanismo delle coroutine e non si propaga allo scope padre.
import kotlinx.coroutines.*
fun main() = runBlocking {
val job = launch {
try {
withTimeout(100) { delay(1000) }
} catch (e: TimeoutCancellationException) {
println("Caught in child: ${e.message}")
}
}
job.join()
println("Parent still running: ${isActive}")
}Pulizia delle risorse in caso di timeout
Utilizzi finally all'interno di withTimeout per rilasciare le risorse anche quando il tempo a disposizione scade.
import kotlinx.coroutines.*
fun main() = runBlocking {
val result = withTimeoutOrNull(150) {
try {
println("Opening resource")
delay(300)
"result"
} finally {
println("Closing resource") // always runs
}
}
println("Result: $result")
}Retry con timeout
Combini il timeout con la logica di retry: tenti un'operazione con un timeout per tentativo e ripeta l'operazione in caso di risultato null.
import kotlinx.coroutines.*
suspend fun tryFetch(attempt: Int): String? = withTimeoutOrNull(200) {
delay(if (attempt < 3) 300L else 100L) // fails first 2 attempts
"success on attempt $attempt"
}
fun main() = runBlocking {
var result: String? = null
var attempt = 1
while (result == null) {
result = tryFetch(attempt++)
}
println(result)
}withTimeout in un ViewModel
Nei ViewModel Android, racchiuda le chiamate al repository in withTimeoutOrNull all'interno di viewModelScope.launch, per mostrare uno stato di errore in caso di risposte lente.
import kotlinx.coroutines.*
// Pseudocode pattern:
suspend fun loadUser(): String = withTimeoutOrNull(3000) {
// repo.getUser()
delay(100)
"Alice"
} ?: "Timeout — using cached data"
fun main() = runBlocking { println(loadUser()) }Nota sulla precisione
withTimeout si basa sul dispatcher delle coroutine. Nei test che utilizzano TestCoroutineScheduler, il tempo è virtuale e può essere fatto avanzare manualmente.
import kotlinx.coroutines.*
// In unit tests with runTest:
// runTest {
// withTimeout(1000) {
// delay(999) // virtual time — completes instantly
// println("done")
// }
// }
fun main() = runBlocking {
println("Use runTest for virtual-time timeout testing")
}Come scegliere tra i due
Utilizzi withTimeout quando il timeout rappresenta un errore. Utilizzi withTimeoutOrNull quando il timeout è un risultato previsto, ad esempio in caso di cache miss o di prefetch facoltativo.
import kotlinx.coroutines.*
fun main() = runBlocking {
// Mandatory: throw on timeout
// withTimeout(500) { criticalOp() }
// Optional: null on timeout
val cached = withTimeoutOrNull(50) {
delay(200); "fresh"
} ?: "stale"
println(cached)
}Verifica rapida
Che cosa restituisce withTimeoutOrNull quando il blocco supera il limite di tempo?
Riepilogo
withTimeout genera un'eccezione in caso di timeout; withTimeoutOrNull restituisce null. Entrambe annullano il blocco in modo cooperativo ed eseguono i blocchi finally. Utilizzi finally per la pulizia delle risorse e withTimeoutOrNull quando il timeout è un risultato previsto.
Domande Frequenti
La lezione «withTimeout e withTimeoutOrNull» è gratuita?
Sì — il testo completo di «withTimeout e withTimeoutOrNull» è gratuito qui sul web. Per esercitarvi in modo interattivo (un editor di codice integrato e un tutor IA 24/7) e sbloccare il resto del corso Kotlin Academy, passa a CoddyKit PRO. Il corso Kotlin Academy include 4 lezioni in totale.
Cosa imparerò in «withTimeout e withTimeoutOrNull»?
Limiti il tempo di esecuzione con wrapper di timeout e gestisca TimeoutCancellationException. Eserciti Kotlin Academy con codice pratico che esegui direttamente nel browser, e un tutor IA 24/7 risponde alle tue domande mentre lavori sulla lezione.
Ho bisogno di esperienza per iniziare Kotlin Academy?
Non è richiesta alcuna esperienza precedente. Kotlin Academy su CoddyKit è strutturato per principianti e studenti avanzati, quindi puoi iniziare da qui o dall'inizio e procedere al tuo ritmo. Questa è la lezione 2 di 4.
Quanto tempo richiede la lezione «withTimeout e withTimeoutOrNull»?
La maggior parte delle lezioni CoddyKit richiede circa 5–10 minuti. Ogni lezione è breve e interattiva, quindi fai progressi costanti e riprendi esattamente da dove hai lasciato su web e app.
Posso scrivere ed eseguire codice in questa lezione Kotlin Academy?
Sì. Ogni lezione Kotlin Academy include un editor di codice integrato, quindi scrivi ed esegui codice reale direttamente nel tuo browser e ricevi feedback istantaneo dall'IA — nessuna configurazione locale necessaria.
Tutte le lezioni di questo corso
- Cancellazione cooperativa: isActive ed ensureActive
- withTimeout e withTimeoutOrNull
- Pulizia con finally e NonCancellable
- Propagazione della cancellazione nelle gerarchie di coroutine