CoroutineScope — bu nədir, həyat dairəsi və korutinlərdə işləməsi

Müəllif: IT Sectr Dərc olunub: 2026-06-22 Oxuma vaxtı: 10 dəq

CoroutineScope — Kotlin interfeysidir, korutinin həyat müddətini müyyənləşdirir və yeni korutinlər başlatmaq üçün kontekst təmin edir. Kotlin sənədləşdirməsinə, 2025 görə, hər bir CoroutineScope nüsxəsi CoroutineContext saxlayır və orada başladılmış bütün korutinləri idarə edir. Scope başa çatdıqda (cancel), bütün alt korutinlər avtomatik ləğv edilir ki, bu da yaddaş sızıntılarının qarşısını alır.

Əsas məqamlar

  • CoroutineScope — yeganə CoroutineContext sahəsi olan, korutinlərin həyat dövrünü müyyənləşdirən interfeys
  • Job — ləğvə cavabdeh olan kontekst elementi: scope-un ləğv edilməsi bütün alt korutinləri ləğv edir
  • Struktur rəqabət — alt korutinlərin ana scope-a bağlı olduğu prinsip
  • GlobalScope — bütün tətbiq üçün scope, sızıntı riski səbəbindən tövsiyə edilmir
  • supervisorScope — bir alt korutinin ləğv edilməsinin digərlərini ləğv etmədiyi xüsusi scope

Kotlin-də CoroutineScope nədir?

CoroutineScope — kotlinx.coroutines kitabxanasından korutinlər üçün konteyner rolunu oynayan fundamental interfeysdir. O, korutinlərin həyat sərhəddlərini müyyənləşdirir: scope başa çatdıqda, onun daxilindəki bütün korutinlər avtomatik ləğv edilir.

kotlin
public interface CoroutineScope {
    public val coroutineContext: CoroutineContext
}

Interfeys yalnız bir sahə ehtiva edir — coroutineContext. Onun vasitəsilə scope daxilində başıdılmış bütün korutinlər üçün dispetçer (Dispatcher), tapşırıq (Job), istisna idarəetməsi və kontekstin digər elementlərini təmin edir.

kotlinx.coroutines kitabxanasında rol

Bütün korutin başlatma funksiyaları — launch, async, runBlocking — CoroutineScope üzərində genişləndirmə funksiyalarıdır. Bu o deməkdir ki, onları yalnız scope obyekti olduqda çağırmaq olar. Belə bir dizayn hər bir korutinin aşkar müəyyənləşmiş valideyn və həyat dövrünə malik olmasını təmin edir.

CoroutineScope harada tətbiq olunur

Android-də hər bir memarlıq komponentinin öz scope-u var: ViewModel üçün viewModelScope, Activity/Fragment üçün lifecycleScope. Server tətbiqlərində scope HTTP sorğusuna və ya verilənlər bazası ilə əlaqə hovuzuna bağlana bilər.

CoroutineScope necə işləyir: Job və struktur rəqabət

CoroutineScope-un daxili quruluşunu başa düşmək Job konsepsiyası və struktur rəqabət prinsipi ilə tanışlıq tələb edir.

Job — korutin tapşırığı

Hər bir korutin başıdıldıqdan sonra Job obyekti qaytarır (və ya async üçün Deferred). Job müəyyən həyat dövrü olan bir tapşırığı təmsil edir: New, Active, Completing, Completed, Cancelling, Cancelled. Job obyektləri ağacşəkilli struktur yaradır:

  • Ana Job — korutinin başıdıldığı scope
  • Alt Job — launch/async vasitəsilə başıdılmış hər bir korutin
  • Valideynin ləğv edilməsi → bütün uşaqların ləğv edilməsi
  • Uşaqda istisna → valideynin ləğv edilməsi (supervisorScope istisna olmaqla)

Struktur rəqabət prinsipi

Struktur rəqabət — Kotlin Coroutines-in əsas memarlıq prinsipi olub, korutinin həyat müddətinin onun scope-un həyat müddətinə bağlı olduğunu bildirir. Bu, korutinin scope başa çatdıqdan sonra da yaşamağa davam etdiyi „fire-and-forget” modelindən fərqlənir. Struktur rəqabətin üstünlükləri:

  • Proqnozlaşdırıla bilən həyat dövrü — scope başa çatdıqda bütün korutinlərin dayandırılması təmin edilir
  • Avtomatik səhv idarəetməsi — hər hansı alt korutindəki istisna scope-a yayılır
  • Sızıntıların olmaması — scope başa çatdıqdan sonra heç bir korutin aktiv qalmır
  • Aşkar iyerarxiya — kod paralel əməliyyatların məntiqi quruluşunu əks etdirir

CoroutineScope-un həyat dövrü

scope.cancel() çağırıldıqda, Job scope Cancelled vəziyyətinə keçir və bu, bütün alt Job-ları rekursiv şəkildə ləğv edir. Ləğv edildikdən sonra scope yalnız yeni CoroutineScope nüsxəsi yaradılmaqla təkrar istifadə edilə bilər.

CoroutineScope-un yaradılması və konfiqurasiyası

CoroutineScope fabrik funksiyası və ya sinifdə interfeysin tətbiqi ilə yaradıla bilər. Hər iki yanaşmanı nəzərdən keçirək.

CoroutineScope() fabrik funksiyası

kotlin
val scope = CoroutineScope(Dispatchers.Default + SupervisorJob())

scope.launch {
    println("${Thread.currentThread().name} üzərində işləyir")
}

Fabrik funksiyası CoroutineContext qəbul edir və göstərilən kontekstlə scope yaradır. Nümunədə CPU intensiv tapşırıqlar üçün Dispatchers.Default və alt korutinlər arasında istisnaları təcrid edən SupervisorJob istifadə olunur.

Kompozisiya vasitəsilə interfeysin tətbiqi

kotlin
class MyRepository {
    private val scope = CoroutineScope(Dispatchers.IO + Job())

    suspend fun fetchData(): Data = scope.async {
        api.getData()
    }.await()

    fun cleanup() {
        scope.cancel()
    }
}

Scope-u sinif sahəsi kimi saxlayır və onu ləğv etmək üçün əl ilə cleanup çağırırıq. Bu, idarə olunan həyat dövrü olan komponentlər — məsələn, repozitoriyalar və ya menecerlər üçün uyğundur.

Deleqasiya vasitəsilə tətbiq

Kotlin by açar sözü vasitəsilə CoroutineScope tətbiqini deleqasiya etməyə imkan verir:

kotlin
class DataLoader : CoroutineScope by CoroutineScope(Dispatchers.IO) {
    fun load() {
        launch {
            // korutin DataLoader scope-da işləyir
        }
    }
}

Bu yanaşma sinfin özü scope olduqda və korutin başlatma metodlarını təmin etmək istədikdə rahatdır. Bununla belə, ehtiyatlı olmaq lazımdır: sinif CoroutineScope-un bütün metodlarını, o cümlədən cancel-i miras alır ki, bu da inkapsulyasiyanı poza bilər.

GlobalScope və fərqləşdirilmiş CoroutineScope

GlobalScope — bütün tətbiq üçün CoroutineScope sinqletonudur. Onun istehsalat kodunda istifadəsi rəsmi olaraq tövsiyə edilmir.

GlobalScope problemləri

  • Struktur rəqabətin olmaması — GlobalScope-da korutinlər komponentin həyat dövrünə bağlı deyil
  • Yaddaş sızıntıları — korutin Activity/Fragment bağlandıqdan sonra işləməyə davam edə bilər
  • Çətin test edilə bilmə — GlobalScope testlərdə əvəz edilə bilməz
  • Nəzarətsiz resurs istehlakı — çox sayda korutin gözləniləndən daha uzun işləyə bilər

GlobalScope nə vaxt əsaslandırılır

JetBrains GlobalScope-u yalnız nadir ssenarilərdə icazə verir: bütün Activity-lər bağlandıqdan sonra da işləməli olan tətbiq səviyyəli fon prosesləri (məsələn, verilənlərin sinxronizasiyası, analitika). Lakin bu hallarda belə CoroutineScope(SupervisorJob()) ilə öz scope-unu yaratmaq daha üstün tutulur.

Tövsiyə

Həmişə fərqləşdirilmiş CoroutineScope-dan aşkar həyat dövrü idarəetməsi ilə istifadə edin. Android-də bunlar viewModelScope və lifecycleScope-dur. Server tətbiqlərində hər sorğu və ya əlaqə hovuzu üçün scope yaradın.

coroutineScope vs supervisorScope: fərq nədir

Hər iki funksiya paralel tapşırıqlar üçün müvəqqəti scope yaradan suspend funksiyalardır, lakin onların istisnalar zamanı davranışı prinsipial olaraq fərqlənir.

XarakteristikacoroutineScopesupervisorScope
Səhv zamanı davranışAlt korutindəki istisna bütün digərlərini ləğv edirAlt korutindəki istisna digərlərini ləğv etmir
Səhvin yayılmasıBəli, ilk istisna xaricə yayılırBəli, ilk istisna xaricə yayılır
Defolt JobJob() — alt korutinlər valideynə bağlıdırSupervisorJob() — alt korutinlər bir-birindən asılı deyil
Tipik istifadə halıBir neçə addımdan ibarət atom əməliyyatMüstəqil paralel tapşırıqlar (UI yükləmələri)

coroutineScope nə vaxt seçilməlidir

coroutineScope-dan bir neçə paralel əməliyyat vahid atom əməliyyat təşkil etdikdə istifadə edin. Məsələn, üç serverdən verilənlərin yüklənməsi: bir sorğu uğursuz olarsa, qalanların mənası yoxdur.

kotlin
suspend fun loadProductPage(): ProductPage = coroutineScope {
    val product = async { api.getProduct() }
    val reviews = async { api.getReviews() }
    ProductPage(product.await(), reviews.await())
}

getProduct və ya getReviews istisna atarsa — hər iki korutin ləğv edilir və istisna çağıran koda yayılır.

supervisorScope nə vaxt seçilməlidir

supervisorScope-dan paralel əməliyyatlar bir-birindən asılı olmadıqda istifadə edin. Məsələn, bir neçə müstəqil bölmədə profil məlumatlarının yüklənməsi: tövsiyələr bölməsi uğursuz olarsa, profil başlığı və dost siyahısı göstərilməlidir.

CoroutineScope ilə işləyərkən tipik səhvlər

Kotlin-də CoroutineScope istifadə edərkən proqramçıların ən çox yol verdiyi səhvləri nəzərdən keçirək.

Səhv 1: Scope-u ləğv etməyi unutmaq

Korutin sızıntısının ən geniş yayılmış ssenarisi — komponent başa çatdıqda cancel çağırmadan scope yaratmaqdır. Scope ləğv edilməzsə, korutinlər obyektlərə istinadları saxlayaraq işləməyə davam edir. Android-də avtomatik ləğv edilən viewModelScope və ya lifecycleScope-dan istifadə edin.

Səhv 2: Activity və ya Fragment-də GlobalScope istifadəsi

GlobalScope Android komponentlərinin həyat dövrünə məhəl qoymur. Activity bağlandıqdan sonra GlobalScope-da başıdılmış korutin yenə də işləməyə və UI-nı yeniləməyə çalışacaq — bu da crash-a səbəb olacaq. UI komponentləri üçün həmişə lifecycleScope istifadə edin.

Səhv 3: Ləğv edilmiş scope-un təkrar istifadəsi

cancel() çağırıldıqdan sonra scope təkrar istifadə edilə bilməz — onun daxilindəki bütün korutinlər artıq tamamlanmışdır. Fabrik funksiyası vasitəsilə yeni CoroutineScope nüsxəsi yaradın. Job() təkrar aktivləşdirməni dəstəkləmir.

Səhv 4: CoroutineScope interfeysinin səhv deleqasiyası

by vasitəsilə deleqasiya zamanı sinif istənilən yerdən çağırıla bilən ictimai cancel() metodu alır ki, bu da inkapsulyasiyanı pozur. Scope-u şəxsi sahə kimi saxlayın, interfeysi deleqasiya etməyin.

Tez-tez verilən suallar

CoroutineScope CoroutineContext-dən nə ilə fərqlənir?

CoroutineScope — CoroutineContext-ə sahib olan və korutinlərin həyat dövrünə cavabdeh olan interfeysdir. CoroutineContext — korutinin “necə” yerinə yetirildiyini müyyənləşdirən elementlər toplusudur (dispetçer, job, səhv idarəetməsi). Fərqlərdən biri: scope korutinləri yaradır, context onların davranışını idarə edir.

SupervisorJob ilə CoroutineScope yaratmaq olarmı?

Bəli, bu standart nümunədir: CoroutineScope(Dispatchers.IO + SupervisorJob()). SupervisorJob alt korutinlərdən birində istisna olduqda kaskad ləğv edilməsinin qarşısını alır. Bu, birindəki səhvin digərlərini dayandırmaması lazım olan müstəqil paralel tapşırıqlar üçün faydalıdır.

CoroutineScope neçə korutin saxlaya bilər?

Scope-da korutinlərin sayı ilə bağlı məhdudiyyət yoxdur — onlar yalnız mövcud yaddaş və dispetçer parametrləri ilə məhdudlaşır. Praktiki hədd adətən bir scope-da minlərlə aktiv korutin təşkil edir. Bununla belə, çox sayda korutin memarlıq problemlərinə işərə edə bilər.

CoroutineScope ilə kodu necə test etmək olar?

Düzgün üsul scope-u konstruktor vasitəsilə sinfə ötürmək və ya kotlinx-coroutines-test-dən runBlockingTest / runTest istifadə etməkdir. Testlərdə scope-u TestCoroutineDispatcher ilə əvəz edə və korutinlərin icrasını əl ilə idarə edə bilərsiniz.

Bir korutinin öz scope-u ola bilərmi?

Xeyr, scope korutin üçün xarici konteynerdir. Korutinin özü scope deyil. Bununla belə, korutin daxilində alt korutinləri paralel başlatmaq üçün coroutineScope və ya supervisorScope vasitəsilə yeni scope yaradıla bilər.

Xülasə

  • CoroutineScope — coroutineContext sahəsi olan, orada başıdılmış korutinlərin həyat dövrünü müyyənləşdirən interfeys
  • Struktur rəqabət — scope-un ləğv edilməsi bütün alt korutinləri avtomatik ləğv edir, yaddaş sızıntılarının qarşısını alır
  • Job və SupervisorJob — iki səhv idarəetmə rejimi: kaskad ləğv (Job) və təcrid olunmuş səhvlər (SupervisorJob)
  • GlobalScope — həyat dövrünə bağlı olmadığı üçün istehsalatda tövsiyə edilmir
  • coroutineScope vs supervisorScope — atom paralel əməliyyatlar müqabilində müstəqil paralel tapşırıqlar
  • viewModelScope və lifecycleScope — Android üçün hazır scope-lar, komponent başa çatdıqda avtomatik ləğv edilir
  • Fabrik funksiyası — CoroutineContext + aşkar cancel çağırışı ilə scope yaratmağın üstünlüklü üsulu

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.

Layihəni müzakirə et

Həm də oxuyun