Coroutine Builder: co to jest, typy builderów korytyn i jak działają

Autor: IT Sectr Opublikowano: 2026-06-21 Czas czytania: 8 min

Coroutine Builder — funkcje Kotlin Coroutines, które tworzą i uruchamiają korytyny, określając sposób ich wykonania. Builderzy launch, async, runBlocking i produce pokrywają różne scenariusze: od zadań w tle po równoległe obliczenia ze zwracaniem wyniku. Według danych JetBrains, 2024, Coroutine Builder jest podstawą modelu korytyn, zapewniając ustrukturyzowaną współbieżność i zarządzanie cyklem życia.

Najważniejsze

  • Coroutine Builder — funkcja tworząca korytynę w określonym CoroutineScope
  • launch — uruchamia korytynę bez zwracania wyniku, zwraca obiekt Job
  • async — uruchamia korytynę ze zwracaniem Deferred, pozwalając uzyskać wynik przez await()
  • runBlocking — blokuje bieżący wątek, używany jako most między blocking i suspending kodem
  • produce — tworzy korytynę z kanałem do strumieniowego przesyłania danych (przestarzałe na rzecz Flow)

Czym jest Coroutine Builder?

Coroutine Builder — to funkcja rozszerzająca Kotlin, która przyjmuje CoroutineScope i suspend-blok, tworząc i uruchamiając nową korytynę. Każdy builder określa, jak korytyna będzie wykonywana: ze zwracaniem wyniku lub bez, z blokowaniem wątku lub asynchronicznie. Builderzy są punktami wejścia do modelu korytyn w języku.

Wszystkie builderzy działają przez CoroutineScope, który zarządza cyklem życia korytyn potomnych. Po anulowaniu scope wszystkie uruchomione przez niego korytyny są automatycznie anulowane — to zasada ustrukturyzowanej współbieżności. Takie podejście zapobiega wyciekom korytyn i gwarantuje przewidywalne zakończenie.

kotlin
import kotlinx.coroutines.*

fun main() = runBlocking {
    // Builderzy działają wewnątrz CoroutineScope
    val job = launch {
        delay(1000L)
        println("Świecie!")
    }
    println("Cześć,")
    job.join()
}

Główne typy builderów korytyn

Kotlin udostępnia cztery wbudowane builderzy korytyn: launch, async, runBlocking i produce. Każdy z nich ma swój typ zwracany i zakres zastosowania. Do programowania mobilnego na Android głównymi są launch i async — działają w sposób nieblokujący i integrują się z komponentami architektonicznymi.

BuilderTyp zwracanyBlokowanie wątkuScenariusz
launchJobNieZadania fire-and-forget
asyncDeferred<T>NieObliczenia równoległe
runBlockingTTakTesty, funkcja main
produceReceiveChannel<E>NiePrzesyłanie strumieniowe (deprecated)

Każdy builder przyjmuje dodatkowe parametry: CoroutineStart (strategia uruchamiania), CoroutineContext (dyspozytor, wyjątki) i nazwany blok kodu. Domyślnie korytyna uruchamiana jest natychmiast (CoroutineStart.DEFAULT).

launch: uruchomienie fire-and-forget

launch — najczęściej używany builder w programowaniu na Androida. Uruchamia korytynę, która nie zwraca wyniku, i zwraca obiekt Job do zarządzania jej cyklem życia. To idealny wybór dla operacji, gdzie potrzebny jest tylko efekt uboczny: zapis do bazy danych, wysyłka analityki, aktualizacja UI.

Składnia i użycie launch

Builder launch przyjmuje CoroutineScope, opcjonalny CoroutineContext i suspend-blok. Zwracany Job pozwala anulować korytynę, czekać na jej zakończenie lub sprawdzić status.

kotlin
val scope = CoroutineScope(Dispatchers.IO + SupervisorJob())
val job: Job = scope.launch(CoroutineStart.LAZY) {
    val data = fetchFromNetwork()
    saveToDatabase(data)
}
job.start()
job.join()

Parametr CoroutineStart.LAZY opóźnia uruchomienie do jawnego wywołania start() lub join(). Jest to przydatne do opóźnionej inicjalizacji i warunkowego uruchamiania. Do standardowego natychmiastowego uruchomienia używany jest CoroutineStart.DEFAULT lub parametr jest pomijany.

async: równoległe obliczenia z wynikiem

async — builder zwracający Deferred<T> — asynchroniczną obietnicę wyniku. Wywołanie await() wstrzymuje korytynę do uzyskania wyniku, nie blokując wątku. To podstawowy mechanizm dla zadań równoległych w korytynach Kotlin.

Uruchamianie dwóch żądań równolegle

async jest szczególnie efektywny, gdy trzeba wykonać kilka niezależnych operacji jednocześnie. W przeciwieństwie do sekwencyjnego wywoływania suspend-funkcji, async uruchamia korytyny równolegle, skracając całkowity czas wykonania.

kotlin
suspend fun fetchUserData(): UserData {
    val deferred1 = CoroutineScope(Dispatchers.IO).async { api.getProfile() }
    val deferred2 = CoroutineScope(Dispatchers.IO).async { api.getSettings() }
    val deferred3 = CoroutineScope(Dispatchers.IO).async { api.getNotifications() }
    return UserData(
        profile = deferred1.await(),
        settings = deferred2.await(),
        notifications = deferred3.await()
    )
}

Deferred dziedziczy po Job, więc async obsługuje wszystkie operacje cyklu życia: anulowanie, oczekiwanie na zakończenie, obsługę wyjątków. Po anulowaniu scope korytyny potomne Deferred są anulowane automatycznie.

runBlocking: most do świata blocking

runBlocking — jedyny builder, który blokuje bieżący wątek do zakończenia korytyny. Tworzy nowy CoroutineScope i uruchamia przekazaną korytynę, blokując wywołujący wątek. Używany w punktach wejścia main(), w testach i przy integracji z blocking-kodem.

Kiedy runBlocking jest niezbędny

runBlocking jest uzasadniony w trzech scenariuszach: punkt wejścia aplikacji (main), testy jednostkowe suspend-funkcji oraz integracja z bibliotekami callback-based, gdzie nie można użyć suspend. W kodzie produkcyjnym Androida używanie runBlocking na głównym wątku kategorycznie nie jest zalecane.

kotlin
class CoroutineTest {
    @Test
    fun `test suspend function`() = runBlocking {
        val result = mySuspendFunction()
        assertEquals("expected", result)
    }
}

Do testów zaleca się używanie kotlinx-coroutines-test z TestCoroutineDispatcher zamiast runBlocking — zapewnia to kontrolę nad czasem i unika blokad w środowisku testowym.

Jak wybrać odpowiedni builder

Wybór Coroutine Builder zależy od zwracanego wyniku i scenariusza wykonania. Jeśli operacja nie wymaga zwracania danych — użyj launch. Jeśli potrzebny jest wynik operacji asynchronicznej — async. runBlocking stosuj tylko do bridging, a produce zastąp Flow dla strumieni reaktywnych.

Praktyczne zalecenia dla Androida

W projektach Android używających Kotlin Coroutines główną parą builderów są launch i async. launch jest używany w ViewModel i UseCases do uruchamiania korytyn, a async — do równoległych żądań do sieci lub bazy danych. Nowoczesne biblioteki (Ktor, Room) już obsługują suspend-funkcje, co minimalizuje potrzebę bezpośredniego używania async.

  • launch — do fire-and-forget (logowanie, analityka, buforowanie)
  • async — do równoległych żądań z łączeniem wyników
  • runBlocking — tylko w main() i testach (nie w production na Main-wątku)
  • produce — zastąp na Flow / SharedFlow / StateFlow

Często zadawane pytania

Czym różni się launch od async w Kotlin?

launch zwraca Job i nie zwraca wyniku wykonania, a async zwraca Deferred<T> — obiekt, z którego można uzyskać wynik przez await(). launch jest używany do operacji fire-and-forget, async — do zadań zwracających dane.

Czy można używać runBlocking w Android Activity?

Nie jest zalecane. runBlocking na głównym wątku powoduje ANR i blokuje UI. Używaj lifecycleScope.launch wewnątrz Activity i Fragment — to wbudowane rozwiązanie bez blokad.

Co zwraca builder launch?

Builder launch zwraca obiekt Job, który pozwala kontrolować cykl życia korytyny: anulować (cancel), czekać na zakończenie (join), sprawdzić status (isActive, isCompleted, isCancelled).

Czym jest Deferred w Kotlin Coroutines?

Deferred<T> — to asynchroniczna obietnica wyniku, zwracana przez builder async. Dziedziczy po Job i dodaje metody await() do uzyskania wyniku, getCompleted() do nieblokującego dostępu oraz getCompletionExceptionOrNull() do sprawdzania wyjątku.

Jak uruchomić launch z opóźnieniem?

Użyj parametru CoroutineStart.LAZY: scope.launch(start = CoroutineStart.LAZY) { ... }. Następnie wywołaj job.start() lub job.join() do faktycznego uruchomienia. Jest to przydatne do opóźnionej inicjalizacji i warunkowego wykonywania korytyn.

Podsumowanie

  • Coroutine Builder — funkcja tworzenia korytyny, która określa sposób jej wykonania i typ zwracany
  • launch — główny builder dla zadań bez zwracania wyniku, zwraca Job do zarządzania korytyną
  • async — builder dla obliczeń równoległych, zwraca Deferred z możliwością await() wyniku
  • runBlocking — blokujący builder dla main() i testów, niezalecany na głównym wątku Androida
  • Ustrukturyzowana współbieżność gwarantuje automatyczne anulowanie korytyn potomnych przy anulowaniu scope
  • produce jest przestarzały — używaj Flow, SharedFlow lub StateFlow dla reaktywnych strumieni danych
  • Wybór buildera zależy od scenariusza: fire-and-forget → launch, dane równoległe → async, bridging → runBlocking

Opracujemy aplikację mobilną pod klucz

IT Sectr tworzy aplikacje na iOS i Androida dla startupów i firm od 2017 roku. Doradzimy Ci i zaproponujemy najlepsze rozwiązanie.

Omów projekt

Przeczytaj również