Dispatchers — klíčové pojmy, typy dispečerů a jak fungují

Autor: IT Sectr Publikováno: 2026-06-22 Doba čtení: 9 min

Dispatchers v Kotlin Coroutines — komponenty CoroutineContext, které určují vlákna pro provádění korutin: Main (UI vlákno), IO (síť a disk), Default (CPU-intenzivní úlohy) a Unconfined (aktuální vlákno). Každý dispečer spravuje specializovaný fond vláken optimalizovaný pro konkrétní typ práce. Podle průvodce JetBrains, 2024 je výběr správného dispečera kritický pro výkon a stabilitu aplikace.

Hlavní body

  • Dispatchers — předdefinované dispečery korutin, které řídí rozdělování úloh mezi vlákna
  • Dispatchers.Main — UI vlákno Androidu, pro aktualizaci rozhraní a práci s View
  • Dispatchers.IO — fond pro síťové požadavky, čtení/zápis souborů a databáze (až 64 vláken)
  • Dispatchers.Default — fond pro CPU-intenzivní úlohy podle počtu jader procesoru
  • Dispatchers.Unconfined — dědění aktuálního vlákna, bez přepínání

Co jsou Dispatchers?

Dispatchers — implementace rozhraní CoroutineDispatcher, které jsou prvky CoroutineContext. Určují, na kterém vlákně nebo fondu vláken bude korutina provedena. Při vytváření korutiny pomocí launch nebo async může být dispečer předán jako první parametr: launch(Dispatchers.IO) { ... }. Pokud není dispečer zadán, dědí se z vnějšího CoroutineScope.

Kotlin poskytuje čtyři vestavěné dispečery: Main, IO, Default, Unconfined. Každý dispečer používá svůj vlastní fond vláken optimalizovaný pro konkrétní typ operací. Správný výběr dispečera určuje výkon aplikace: chybný výběr vede k zpomalení rozhraní, nevyužití jader CPU nebo neefektivnímu spotřebování vláken.

DispečerFond vlákenMax. vlákenPoužití
Dispatchers.MainJedno (UI)1Aktualizace UI, LiveData, View
Dispatchers.IOFond IO64 (limitedParallelism)Síť, soubory, databáze
Dispatchers.DefaultFond CPUN jaderŘazení, parsování, výpočty
Dispatchers.UnconfinedAktuální vláknoN/AMezioperační úkoly, testy

Dispatchers.Main: UI vlákno

Dispatchers.Main — dispečer provádějící korutiny na hlavním vlákně Androidu. Je určen pro operace související s rozhraním: aktualizace TextView, volání notifyDataSetChanged, práce s LiveData a StateFlow. V Androidu je tento dispečer implementován pomocí Handler (Looper.getMainLooper()).

kotlin
// Správné přepnutí na Main pro aktualizace UI
viewModelScope.launch(Dispatchers.IO) {
    val data = repository.fetchData()
    withContext(Dispatchers.Main) {
        _uiState.value = data
    }
}

Pokud je korutina již na dispečeru Main, dodatečný withContext(Dispatchers.Main) nevytváří režii — dispečer zkontroluje aktuální vlákno a přepnutí přeskočí. withContext je preferovaný způsob přepínání mezi dispečery.

Dispatchers.IO: síť a diskové operace

Dispatchers.IO — dispečer optimalizovaný pro vstupně-výstupní operace: HTTP požadavky (Ktor, OkHttp), čtení a zápis souborů, práce s Room nebo SQLDelight. Ve výchozím nastavení používá fond 64 vláken, škálovatelný pod zátěží. Každý nový IO požadavek může vytvořit další vlákno až do dosažení limitu.

Omezení paralelismu

Pro řízení počtu současných IO operací použijte limitedParallelism(). Tato funkce vytvoří nový dispečer s omezením počtu paralelních vláken, čímž zabraňuje vyčerpání fondu při hromadných operacích.

kotlin
val limitedIo = Dispatchers.IO.limitedParallelism(4)

// Načíst 100 souborů s limitem 4 souběžných operací
coroutineScope {
    val files = (1..100).map { index ->
        async(limitedIo) {
            downloadFile("file_$index")
        }
    }
    files.awaitAll()
}

Používejte IO-dispečer pro všechny operace, kde korutina tráví čas čekáním (I/O-bound). CPU-intenzivní úlohy na IO-dispečeru jsou neefektivní — zabírají vlákna určená pro vstup-výstup, čímž snižují propustnost systému.

Dispatchers.Default: CPU-intenzivní úlohy

Dispatchers.Default — dispečer pro výpočetní operace zatěžující procesor: řazení, filtrování, parsování JSON (Moshi, Kotlinx Serialization), zpracování obrazu, výpočty. Velikost fondu se rovná počtu jader procesoru (nejméně však 2). To zajišťuje maximální zatížení CPU bez přepínání kontextu.

kotlin
suspend fun processData(input: List<RawRecord>): List<ProcessedRecord> {
    return withContext(Dispatchers.Default) {
        input
            .parallelStream()
            .map { transform(it) }
            .toList()
    }
}

Nepoužívejte Dispatchers.Default pro IO operace — zablokuje to vlákna CPU fondu, která by mohla zpracovávat výpočetní úlohy. Rozdělení na IO a Default umožňuje optimálně využívat systémové prostředky: IO vlákna čekají na vstup-výstup, CPU vlákna jsou neustále zaměstnána výpočty.

Dispatchers.Unconfined: aktuální vlákno

Dispatchers.Unconfined — speciální dispečer, který nepřipojuje korutinu k žádnému fondu. Korutina začíná provádění ve stejném vlákně, kde byla volána launch/async, a po pozastavení pokračuje ve vlákně, které volalo resume. Toto chování je vhodné pro mezioperační úkoly, které nevyžadují pevný kontext.

kotlin
fun main() = runBlocking {
    launch(Dispatchers.Unconfined) {
        println("Před zpožděním: ${Thread.currentThread().getName()}")
        delay(500L)
        println("Po zpoždění: ${Thread.currentThread().getName()}")
    }
}

V produkčním kódu se Dispatchers.Unconfined používá zřídka. Hlavní případy: lehké transformace před předáním dat jinému dispečerovi a testy. Pro produkční zatížení používejte explicitní dispečery — Unconfined je nepředvídatelný, protože vlákno provedení závisí na implementaci resume.

Jak vybrat dispečera

Výběr dispečera je určen typem úlohy: UI operace → Main, I/O-bound → IO, CPU-bound → Default, mezioperační → dědění z scope. Pro Android se doporučuje spustit korutinu na tom dispečerovi, kde se provádí hlavní práce, a před aktualizací UI přepnout na Main pomocí withContext.

  • Nespouštějte IO operace na dispečeru Main — blokuje to UI
  • Nespouštějte CPU-intenzivní úlohy na dispečeru IO — neefektivně to spotřebovává vlákna IO fondu
  • Používejte limitedParallelism pro řízení paralelismu při hromadných IO operacích
  • Přepínejte dispečera pomocí withContext, ne vytvářením nového scope
  • Děďte dispečera z scope, pokud korutina nevyžaduje specifický fond

Pro složité scénáře kombinujte dispečery pomocí operátoru +: Dispatchers.IO + SupervisorJob() + CoroutineExceptionHandler. Tím vytvoříte CoroutineContext s určeným dispečerem, zpracováním chyb a izolovanou hierarchií Job.

Často kladené otázky

Jaký je rozdíl mezi Dispatchers.IO a Dispatchers.Default?

Dispatchers.IO používá fond až 64 vláken pro I/O-bound operace (čekání na vstup-výstup), zatímco Dispatchers.Default — fond podle počtu jader CPU pro výpočetní úlohy. Při nedostatku vláken si oba fondy mohou vzájemně půjčovat vlákna.

Mohu si vytvořit vlastní dispečer v Kotlin Coroutines?

Ano, použijte newSingleThreadContext() pro jednovláknový nebo newFixedThreadPoolContext() pro pevný fond. Pro produkci aplikujte limitedParallelism() na základě stávajících dispečerů — je to efektivnější než vytváření nových fondů.

Co se stane při volání Dispatchers.Main na pozadí?

Pokud Dispatchers.Main není k dispozici (např. v JUnit testu nebo službě na pozadí), je vyvolána výjimka IllegalStateException. Pro testy použijte TestCoroutineDispatcher, pro služby na pozadí — Dispatchers.IO nebo Default.

Jak omezit počet paralelních IO operací?

Použijte Dispatchers.IO.limitedParallelism(N), kde N je maximální počet paralelních vláken. Tím zabráníte vyčerpání fondu při hromadných požadavcích a získáte řízený paralelismus.

Kdy použít Dispatchers.Unconfined?

Dispatchers.Unconfined je vhodný pro mezioperační úkoly: lehké transformace dat před předáním jinému dispečerovi, testovací scénáře. V produkčním kódu Androidu se nedoporučuje kvůli nejistému vláknu provedení po pozastavení.

Shrnutí

  • Dispatchers — komponenty CoroutineContext určující vlákna provádění korutin
  • Dispatchers.Main — pro UI operace Androidu, jedno hlavní vlákno
  • Dispatchers.IO — pro síťové a diskové operace, fond až 64 vláken
  • Dispatchers.Default — pro CPU-intenzivní výpočty, fond podle počtu jader
  • Dispatchers.Unconfined — bez vazby na vlákno, pro mezioperační úkoly
  • withContext — hlavní mechanismus přepínání mezi dispečery uvnitř korutiny
  • Špatný výběr dispečera vede k zpomalení UI nebo neefektivnímu využití zdrojů

Vyvineme mobilní aplikaci na klíč

IT Sectr vytváří aplikace pro iOS a Android pro startupy a podniky od roku 2017. Poradíme vám a navrhneme nejlepší řešení.

Prodiskutovat projekt

Přečtěte si také