withTimeout i withTimeoutOrNull
Ograniczaj czas wykonywania za pomocą opakowań timeout i obsługuj TimeoutCancellationException.
withTimeout i withTimeoutOrNull to bezpłatna lekcja Kotlin Academy na CoddyKit. To lekcja 2 z 4. Możesz przeczytać całą lekcję poniżej za darmo — a potem ćwiczyć ją interaktywnie w przeglądarce z wbudowanym edytorem kodu i tutorem AI dostępnym 24/7. To część ścieżki edukacyjnej Kotlin Academy, a Twój postęp synchronizuje się między webem a aplikacją CoddyKit. Kurs Kotlin Academy zawiera 4 lekcji w sumie.
Po co stosować limity czasu?
Korutyny mogą zawiesić się na czas nieokreślony podczas operacji sieciowych lub wejścia-wyjścia. withTimeout anuluje blok, jeśli nie zakończy się on w podanym czasie wyrażonym w milisekundach.
import kotlinx.coroutines.*
fun main() = runBlocking {
try {
withTimeout(200) {
delay(1000) // simulates slow network
println("This never prints")
}
} catch (e: TimeoutCancellationException) {
println("Timed out!")
}
}Podstawy withTimeout
withTimeout(millis) { ... } zgłasza TimeoutCancellationException (podklasę CancellationException), jeśli wykonanie bloku przekroczy limit.
import kotlinx.coroutines.*
suspend fun fetchData(): String {
delay(100)
return "data"
}
fun main() = runBlocking {
val result = withTimeout(500) {
fetchData()
}
println(result) // data
}withTimeoutOrNull
withTimeoutOrNull zwraca null po przekroczeniu limitu zamiast zgłaszać wyjątek, dzięki czemu łatwiej obsługiwać przekroczenie limitu jako normalny przebieg programu.
import kotlinx.coroutines.*
fun main() = runBlocking {
val result: String? = withTimeoutOrNull(200) {
delay(1000)
"done"
}
println(result ?: "Timeout — using default")
}Limit czasu a wartość zwracana
Po pomyślnym wykonaniu obie funkcje zwracają wartość ostatniego wyrażenia w bloku.
import kotlinx.coroutines.*
fun main() = runBlocking {
val response = withTimeoutOrNull(500) {
delay(100)
mapOf("status" to 200, "body" to "OK")
}
println(response?.get("status")) // 200
}Zagnieżdżanie limitów czasu
Wewnętrzne limity czasu wygasają jako pierwsze. Zewnętrzny limit zadziała tylko wtedy, gdy wewnętrzny nie anuluje wykonania wcześniej — jest to przydatne w przypadku limitów dla poszczególnych żądań oraz limitu globalnego.
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 jest obiektem typu CancellationException, dlatego mechanizm korutyn traktuje go jako normalne anulowanie i nie propaguje go do nadrzędnego zakresu.
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}")
}Zwalnianie zasobów po przekroczeniu limitu czasu
Wewnątrz withTimeout należy używać finally, aby zwolnić zasoby nawet po upływie limitu czasu.
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")
}Ponawianie prób z limitem czasu
Połącz limit czasu z logiką ponawiania prób: wykonuj operację z limitem czasu dla każdej próby i ponawiaj ją po otrzymaniu wyniku 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 w ViewModel
W Androidowych obiektach ViewModel wywołania repozytorium należy opakować w withTimeoutOrNull wewnątrz viewModelScope.launch, aby przy wolnych odpowiedziach wyświetlić stan błędu.
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()) }Uwaga dotycząca dokładności
withTimeout korzysta z dyspozytora korutyn. W testach używających TestCoroutineScheduler czas jest wirtualny i można go przesuwać ręcznie.
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")
}Wybór między obiema funkcjami
Użyj withTimeout, gdy przekroczenie limitu czasu jest błędem. Użyj withTimeoutOrNull, gdy jest ono oczekiwanym wynikiem (np. brak danych w pamięci podręcznej lub opcjonalne wstępne pobieranie).
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)
}Szybkie sprawdzenie
Co zwraca withTimeoutOrNull, gdy wykonanie bloku przekroczy limit czasu?
Podsumowanie
withTimeout zgłasza wyjątek po przekroczeniu limitu czasu, a withTimeoutOrNull zwraca null. Obie funkcje kooperacyjnie anulują blok i wykonują bloki finally. Używaj finally do zwalniania zasobów, a withTimeoutOrNull, gdy przekroczenie limitu czasu jest oczekiwanym wynikiem.
Ucz się Kotlin dzięki korepetycjom AI — za darmo
Pisz i uruchamiaj kod w przeglądarce, otrzymuj natychmiastową pomoc od korepetytora AI dostępnego 24/7 i kontynuuj naukę w sieci lub w aplikacji.
- Kursy
- 51
- Lekcje
- 203
Często zadawane pytania
Czy lekcja „withTimeout i withTimeoutOrNull” jest bezpłatna?
Tak — pełny tekst „withTimeout i withTimeoutOrNull” jest dostępny za darmo tutaj w sieci. Aby ćwiczyć ją interaktywnie (wbudowany edytor kodu i tutor AI dostępny 24/7) i odblokować resztę kursu Kotlin Academy, przejdź na CoddyKit PRO. Kurs Kotlin Academy zawiera 4 lekcji w sumie.
Co nauczysz się w „withTimeout i withTimeoutOrNull”?
Ograniczaj czas wykonywania za pomocą opakowań timeout i obsługuj TimeoutCancellationException. Ćwiczysz Kotlin Academy z praktycznym kodem, który uruchamiasz bezpośrednio w przeglądarce, a tutor AI dostępny 24/7 odpowiada na Twoje pytania podczas pracy nad lekcją.
Czy potrzebuję doświadczenia, aby zacząć Kotlin Academy?
Nie wymagamy żadnego doświadczenia. Kotlin Academy w CoddyKit jest strukturyzowany dla początkujących i zaawansowanych użytkowników, więc możesz zacząć tutaj lub od początku i uczyć się w swoim tempie. To lekcja 2 z 4.
Ile czasu zajmuje lekcja „withTimeout i withTimeoutOrNull”?
Większość lekcji CoddyKit trwa około 5–10 minut. Każda lekcja to mały, interaktywny krok, dzięki czemu robisz systematyczne postępy i zawsze wracasz dokładnie do tego samego miejsca — na webie i w aplikacji.
Czy mogę pisać i uruchamiać kod w tej lekcji Kotlin Academy?
Tak. Każda lekcja Kotlin Academy zawiera wbudowany edytor kodu, więc piszesz i uruchamiasz prawdziwy kod bezpośrednio w przeglądarce i od razu otrzymujesz sprzężenie zwrotne od AI — bez konfiguracji na komputerze.
Wszystkie lekcje w tym kursie
- Kooperatywne anulowanie: isActive i ensureActive
- withTimeout i withTimeoutOrNull
- Sprzątanie za pomocą finally i NonCancellable
- Propagacja anulowania w hierarchiach korutyn