Sparround

Coroutines: suspend, scope, dispatcher-lər

Coroutine — dayandırıla bilən (suspendable) hesablama vahididir: thread-i bloklamadan gözləyə bilir. Bir thread minlərlə coroutine icra edə bilər.

Əsas anlayışlar:

  • suspend fun — dayandırıla bilən funksiya; yalnız coroutine içindən və ya başqa suspend funksiyadan çağırılır. suspend özü thread dəyişmir — sadəcə dayanma nöqtəsi verir.
  • CoroutineScope — coroutine-lərin həyat dövrünü idarə edir. Android-də hazır scope-lar: viewModelScope, lifecycleScope.
  • Job — coroutine-in ləğv edilə bilən dəstəyi; SupervisorJob — bir uşağın xətası qardaşlarını ləğv etmir.
  • Dispatchers: Main (UI), IO (şəbəkə/disk), Default (CPU-intensiv hesablama).
  • structured concurrency — hər coroutine bir scope-a bağlıdır: scope ləğv olunanda bütün uşaqlar da ləğv olunur, "itmiş" coroutine qalmır.
kotlin
class AccountViewModel(private val repo: AccountRepository) : ViewModel() {

    fun loadBalance() {
        viewModelScope.launch {                  // Main dispatcher-də başlayır
            _uiState.update { it.copy(isLoading = true) }
            try {
                val balance = withContext(Dispatchers.IO) {
                    repo.fetchBalance()          // şəbəkə çağırışı IO thread pool-da
                }
                _uiState.update { it.copy(balance = balance, isLoading = false) }
            } catch (e: IOException) {
                _uiState.update { it.copy(error = "Şəbəkə xətası", isLoading = false) }
            }
        }
    }
}

ViewModel-də tipik pattern: IO işi, Main-də nəticə

Suallaunchasync
Nə qaytarırJob (nəticəsiz)Deferred<T> — await() ilə nəticə
Nə üçün"Fire and forget" işParalel hesablamaların nəticələri
Exception davranışıDərhal parent-ə ötürülürawait() çağırılana qədər saxlanılır

Cancellation kooperativdir: coroutine yalnız suspension nöqtələrində (delay, withContext, yield) və ya isActive yoxlamasında ləğvi "görür". Sonsuz while(true) dövrü suspension nöqtəsi olmadan ləğv olunmur. CancellationException-ı udmaq (catch edib ötürməmək) klassik bug-dır — onu həmişə yenidən at.

🛠 Tapşırıq

Balans və tranzaksiya tarixçəsini "çəkən" iki suspend funksiya yaz (hər biri delay(1500) ilə imitasiya).

  • Əvvəl ardıcıl çağır, vaxtı ölç (measureTimeMillis).
  • Sonra async + await ilə paralel çağır, vaxtı yenidən ölç.
  • Birində exception at və launch ilə async arasındakı davranış fərqini gör.

Bitdi sayılır: ~3s → ~1.5s fərqini və exception davranışını izah edə bilirsənsə.

📚 Mənbələr və sənədlər