Coroutines (korutinlər) — kotlinx.coroutines kitabxanası vasitəsilə əldə edilən asinxron proqramlaşdırma üçün Kotlin-in yüngül thread-ləridir. JetBrains Kotlin Documentation, 2026-ya görə, Coroutines ənənəvi Thread-lərdən fərqli olaraq, funksiyanın icrasını thread-i bloklamadan dayandırmağa imkan verir. Korutinlər məhdud thread hovuzunda işlədilir və bu onları nativ thread-lərdən min dəfə yüngül edir. Kotlin Coroutines Android Jetpack, Retrofit, Room və Android ekosisteminin digər məşhur kitabxanaları ilə tam inteqrasiya olunub.
Əsas məqamlar
Coroutines (korutinlər) — kotlinx.coroutines kitabxanasında tətbiq olunan Kotlin-də asinxron proqramlaşdırma mexanizmidir. Əməliyyat sistemi thread-lərindən fərqli olaraq, korutinlər müəyyən bir thread-ə bağlı deyil: onlar bir thread-də dayanıb başqa bir thread-də bərpa oluna bilər. Bir thread minimal əlavə xərclə onların arasında keçid edərək minlərlə korutini icra edə bilər.
Korutinlər Kotlin 1.3-də (2018) eksperimental funksiya kimi ortaya çıxdı və Kotlin 1.5-də (2021) stabil oldu. Coroutines callback hell problemini async/await kimi həll edir, lakin daha zəngin API təqdim edir: kanallar (Channel), Flow, Job iyerarxiyasında istisna idarəetməsi və birbaşa Android Lifecycle ilə inteqrasiya.
JetBrains (2025) məlumatlarına görə, hər bir korutin nativ thread üçün 1+ MB-a qarşı təxminən 100 bayt yaddaş sərf edir. Bu, OutOfMemoryError riski olmadan bir tətbiqdə milyonlarla korutini işə salmağa imkan verir. Məhz korutinlərin yüngüllüyü onları Android-də asinxronluq üçün üstünlük verilən alət edir.
Hər bir Kotlin korutini Continuation Passing Style (CPS) vasitəsilə state machine-ə kompilyasiya olunur. Kompilyator hər bir suspend funksiyasına gizli Continuation parametri əlavə edir. Continuation bərpa nöqtəsini və bütün lokal dəyişənləri ehtiva edir. Korutin dayandıqda, runtime Continuation-u saxlayır, bərpa olduqda isə onu Dispatcher hovuzundan istənilən mövcud thread-də bərpa edir.
suspend — funksiyanı dayandırıla bilən kimi qeyd edən Kotlin açar sözüdür. Belə bir funksiya yalnız başqa bir suspend funksiyasından və ya korutindən çağırıla bilər. Suspend funksiyasının daxilində digər suspend funksiyaları istənilən ardıcıllıqla çağırıla bilər və hər bir çağırış nöqtəsi potensial dayandırma nöqtəsidir.
Mexanika sadədir: suspend funksiyası başqa bir suspend funksiyasını çağırdıqda, o, thread-i boşaldaraq həmin nöqtədə dayanır. Çağırılan funksiya tamamlandıqdan sonra runtime qeyd olunmuş yerdən icranı davam etdirir. Buna cooperative cancellation deyilir — heç bir thread bloklanmır.
Vacib: suspend funksiyası standart olaraq asinxron deyil. İcra ardıcıllığı launch və ya async istifadə edilmədikdə seqvensial qalır. suspend yalnız funksiyanın thread-i bloklamadan dayandırılmasına və korutin kontekstinin bir hissəsi olmasına imkan verir. Continuation Passing Style hər bir suspend funksiyasının gizli Continuation callback-i aldığı və kompilyatorun dayandırmaları və bərpaları idarə etmək üçün vəziyyət maşını yaratdığı kompilyasiya modelidir.
CoroutineScope — korutinlərin həyat dövrünü təyin edən kontekstdir. Bütün korutinlər scope daxilində işə salınmalıdır. Scope ləğv edildikdə (məsələn, Activity başa çatdıqda), onun bütün uşaq korutinləri avtomatik ləğv edilir. Bu, fon tapşırıqlarının sızmasının qarşısını alır. Android Jetpack hər bir komponent üçün hazır scope təqdim edir: ViewModel üçün viewModelScope və Activity və Fragment üçün lifecycleScope, müvafiq komponent məhv edildikdə avtomatik ləğv olunur.
Structured Concurrency — korutinin bütün uşaq korutinləri tamamlanana qədər bitməyəcəyinə zəmanət verən prinsipdir. Job iyerarxiyası bir ağac yaradır: kök korutin parent job, uşaqlar isə child jobs yaradır. Parent job-un ləğvi bütün uşaqlara yayılır. Structured Concurrency korutinlərlə thread-lər arasında əsas fərqdir.
| Scope | Harada istifadə olunur | Ləğv |
|---|---|---|
| GlobalScope | Yalnız daemon tapşırıqları üçün | Avtomatik ləğv olunmur |
| viewModelScope | Android ViewModel | ViewModel təmizlənəndə |
| lifecycleScope | Android Activity/Fragment | Lifecycle məhv ediləndə |
| coroutineScope | Suspend funksiyası daxilində | Parent job ləğv ediləndə |
Adi Job bir uşaq korutində səhv olduqda bütün siblings-ləri ləğv edir. SupervisorJob — istisnadır: bir uşaq korutindəki nasazlıq qalanlarına təsir etmir. Bu, bir neçə müstəqil tapşırıq paralel icra edildikdə və onlardan biri digərlərini ləğv etməyə ehtiyac olmadan uğursuz ola bildikdə vacibdir.
Dispatchers korutinlərin hansı thread-lərdə icra olunacağını müəyyən edir. Dispatchers.Main — Android-in əsas UI thread-i. Dispatchers.IO — bloklayan əməliyyatlar üçün hovuz (şəbəkə, disk). Dispatchers.Default — CPU intensiv tapşırıqlar üçün. Dispatchers.Unconfined — cari thread-də başlayır, lakin orada qalacağına zəmanət vermir. Düzgün Dispatcher seçimi performans üçün kritikdir: Default-da IO tapşırığı hesablamalar üçün hovuzu bloklayacaq, IO-da CPU tapşırığı isə lazımsız thread-lər yaradacaq.
withContext — korutin daxilində Dispatcher-i dəyişmək üçün funksiya. Məsələn, JSON parse edən suspend funksiyası hesablama zamanı Dispatchers.Default-ə keçib UI yeniləməsi üçün Dispatchers.Main-ə qayıda bilər. withContext Android inkişafında ən çox istifadə olunan qurucudur.
launch — korutini işə salır, Job qaytarır, nəticə qaytarmır (fire-and-forget). async — korutini işə salır, nəticəni await vasitəsilə əldə etmək üçün Deferred qaytarır. runBlocking — korutini icra etmək üçün cari thread-i bloklayır (yalnız testlər və main funksiyaları üçün). Qurucu seçimi ssenaridən asılıdır: launch hadisələr və yeniləmələr üçün, async nəticə ilə tapşırıqlar üçün, runBlocking yalnız testlər və ya giriş nöqtələri üçün uyğundur.
Üç praktik ssenariyə baxaq: launch ilə əsas korutin, async ilə paralel çağırış və SupervisorJob ilə səhv idarəetməsi.
viewModelScope.launch ViewModel kontekstində korutini işə salır. ViewModel təmizlənəndə korutin avtomatik ləğv edilir.
class ProfileViewModel : ViewModel() {
fun loadUser() {
viewModelScope.launch(Dispatchers.IO) {
val user = api.fetchUser()
withContext(Dispatchers.Main) {
showUser(user)
}
}
}
}
coroutineScope async ilə üç sorğunu paralel işə salır. Nəticələr .await() vasitəsilə toplanır. Sorğulardan hər hansı biri uğursuz olarsa, hamısı ləğv edilir.
suspend fun loadDashboard(): Dashboard = coroutineScope {
val user = async { api.fetchUser() }
val posts = async { api.fetchPosts() }
val stats = async { api.fetchStats() }
Dashboard(user.await(), posts.await(), stats.await())
}
SupervisorJob hər bir korutinin müstəqil başa çatmasına imkan verir. Bir sorğudakı səhv qalanlarını ləğv etmir.
val scope = CoroutineScope(SupervisorJob() + Dispatchers.IO)
scope.launch {
try { api.fetchUsers() } catch (e: Exception) { log(e) }
}
scope.launch {
try { api.fetchPosts() } catch (e: Exception) { log(e) }
}
Thread-lər — əməliyyat sistemi primitividir. Hər bir thread-in öz yığını (~1 MB) var və yaradılması və dəyişdirilməsi üçün sistem çağırışı tələb edir. Korutinlər — OS-yə bağlı olmayan dil primitividir. Vəziyyəti saxlamaq üçün Continuation-dan istifadə edir və sistem çağırışları olmadan runtime səviyyəsində dəyişilir.
Google (2025) məlumatlarına görə, korutinlərin thread-lər əvəzinə istifadəsi Android tətbiqlərində fon tapşırıqları üçün yaddaş istehlakını 90–95% azaldır. Bütün müasir Android kitabxanaları (Retrofit, Room, WorkManager) suspend funksiyaları vasitəsilə korutinlər üçün daxili dəstəyə malikdir. Ktor (JetBrains-in HTTP klient framework-u) da tamamilə korutinlər üzərində qurulub, callback API olmadan hər sorğu üçün suspend-funksiyalar təqdim edir. Room DAO-da suspend-funksiyalar vasitəsilə korutinləri dəstəkləyir ki, bu da əsas thread-i bloklamadan verilənlər bazası sorğularını yerinə yetirməyə imkan verir.
Thread-lər JNI vasitəsilə nativ kod, vaxt məhdudiyyəti olmayan CPU intensiv bloklayan çağırışlar (video render, simulyasiyalar) və C kitabxanaları ilə inteqrasiya üçün zəruri olaraq qalır. Qalan hər şey üçün — korutinlər.
Tez-tez verilən suallar
Korutin — mövcud thread-də icra olunan dayandırıla bilən iş vahididir. Thread öz yığını olan sistem resursudur. Korutinlər thread-lərdən minlərlə dəfə yüngüldür və dayandırıldıqda resursları bloklamır.
Dispatchers.IO bloklayan I/O əməliyyatları (şəbəkə, fayllar) üçün nəzərdə tutulub və lazım olduqda yeni thread-lər yarada bilər. Dispatchers.Default CPU intensiv hesablamalar üçün sabit ölçülü hovuza malikdir (prosessor nüvələrinin sayı).
Job.cancel() korutini və onun bütün uşaqlarını ləğv edir. Korutin daxilində ləğvi yoxlamaq üçün ensureActive() istifadə edin — korutin ləğv edilibsə CancellationException atır.
Bəli — kotlinx-coroutines-rx3 kitabxanası vasitəsilə. Observable/Single-i suspend funksiyalarına və əksinə flowable vasitəsilə çevirmək üçün awaitSingle, awaitFirst və digər funksiyalar təqdim edir.
Flow — korutinlər üçün RxJava Observable-in analoqu olan soyuq asinxron məlumat axınıdır. Flow dəyərləri ardıcıl olaraq emit edir və istisna və ya uğurla başa çatır. Map, filter, catch və digər operatorları dəstəkləyir.
Nəticə
Açar təslim mobil tətbiq hazırlayacağıq
IT Sectr 2017-ci ildən startaplar və bizneslər üçün iOS və Android tətbiqləri yaradır. Sizə məsləhət verəcəyik və ən yaxşı həlli təklif edəcəyik.
Həm də oxuyun