withContext: nima, kontekstni o'zgartirish va korutinalarda ishlash

Muallif: IT Sectr Nashr etilgan: 2026-06-22 O'qish vaqti: 9 daq

withContext — korutina ichida bajarilish kontekstini almashtiruvchi funksiya bo'lib, ko'rsatilgan kod bloki uchun vaqtinchalik oqim yoki dispetcherni o'zgartiradi va natijani asl kontekstga qaytaradi. JetBrains, 2025 ma'lumotlariga ko'ra, withContext tarmoq so'rovlari va disk operatsiyalari uchun korutinalarning eng ko'p ishlatiladigan vositalaridan biridir. Funksiya blok tugagandan so'ng korutinaning asl dispetcherda bajarilishni davom ettirishini kafolatlaydi, bu esa tasodifiy oqim xavfsizligi xatolarining oldini oladi.

Asosiy fikrlar

  • withContext — berilgan kod bloki uchun CoroutineContext-ni o'zgartiruvchi va natijani qaytaruvchi to'xtatuvchi funksiya
  • Dispatchers.IO — tarmoq va disk operatsiyalarida fon oqimiga o'tish uchun odatiy argument
  • Dispatchers.Main — withContext blok tugagandan so'ng bajarilishni avtomatik qaytaradigan asl kontekst
  • Ketma-ket chaqiruvlar — withContext kodni launch va async-dan farqli ravishda ketma-ket bajaradi, bu operatsiyalar tartibini nazorat qilishni soddalashtiradi
  • Val natijasi — withContext lambda-ning oxirgi qatorida return orqali to'g'ridan-to'g'ri qiymat qaytaradi, await yoki joinni talab qilmaydi

Kotlin-da withContext nima?

withContext — kotlinx.coroutines paketidan to'xtatuvchi funksiya bo'lib, berilgan kod blokini belgilangan CoroutineContext-da bajaradi va natijani asl kontekstga qaytaradi. Funksiya imzosi quyidagicha:

kotlin
suspend fun  withContext(
    context: CoroutineContext,
    block: suspend CoroutineScope.() -> T
): T

context parametri istalgan CoroutineContext-ni qabul qiladi — ko'pincha standart Dispatchers.IO, Dispatchers.Default yoki Dispatchers.Main dan biri. Blok aynan shu kontekstda bajariladi va natija withContext chaqirilgan joyga qaytariladi.

Asosiy xususiyat: avtomatik qaytish

Lambda tugagandan so'ng, withContext kafolatlangan holda bajarilishni asl dispetcherga qaytaradi. Bu shuni anglatadiki, dasturchi fon operatsiyasidan so'ng qo'lda withContext(Dispatchers.Main) chaqirishi shart emas — qaytish avtomatik sodir bo'ladi. Ushbu xatti-harakat Kotlin Coroutines spetsifikatsiyasida 1.3 versiyasidan boshlab belgilangan.

withContext qayerda qo'llaniladi

Android rivojlanishi — withContext ning asosiy qo'llanish sohasi. Odatiy stsenariy: ViewModel asosiy oqimda korutina ishga tushiradi, ichida tarmoq so'rovi uchun withContext(Dispatchers.IO) chaqiriladi va natija Main-ga avtomatik qaytgandan so'ng UI ni yangilash uchun ishlatiladi. Ushbu yondashuv MVVM arxitekturasining asosini tashkil etadi va Google tomonidan korutinalar bo'yicha rasmiy qo'llanmada tavsiya etiladi.

withContext qanday ishlaydi: dispetcherlarni almashtirish

withContext ni tushunish uchun CoroutineContext va uning asosiy komponenti — dispetcher (Dispatcher) bilan tanishish kerak. Har bir korutina kontekst elementlari to'plamiga ega bo'lib, ular orasida dispetcher kod qaysi oqim yoki oqimlar havzasida bajarilishini aniqlaydi.

withContext uchun standart dispetcherlar

DispetcherMaqsadHavza hajmi
Dispatchers.MainAsosiy UI oqimi (Android, JavaFX, Swing)1 (asosiy oqim)
Dispatchers.IODisk va tarmoq operatsiyalari64 oqim (chegara o'sadi)
Dispatchers.DefaultCPU intensiv hisoblashlarmax(2, yadrolar soni)
Dispatchers.UnconfinedRuxsat etilgan oqimsizcheklanmagan

withContext yangi korutina yaratmasligini tushunish muhim — u faqat mavjud korutina uchun kontekstni o'zgartiradi. Bu uni launch va async-dan farqlaydigan asosiy xususiyatdir, chunki ular yangi korutinalar yaratadi. Ichki amalga oshirish optimallashtirilgan: so'ralgan kontekst joriy bilan mos kelsa, almashtirish sodir bo'lmaydi — funksiya bir xil dispetcherda bajariladi.

withContext oqimni QACHON o'zgartirmaydi

Dispatchers.Main withContext(Dispatchers.Main) ichida almashtirishga sabab bo'lmaydi — Kotlin Coroutines kontekstlarning bir xilligini taniydi va keraksiz operatsiyani o'tkazib yuboradi. Xuddi shunday, allaqachon Default-da ishlayotgan korutina ichida withContext(Dispatchers.Default) hech qanday qo'shimcha yuk yaratmaydi. Ushbu optimallashtirish ContinuationInterceptor da amalga oshirilgan.

withContext vs launch va async: qachon nimani tanlash

Yangi boshlanuvchilar tez-tez withContext ni launch va async bilan aralashtiradilar, chunki uchala funksiya ham korutinalar va kontekst bilan ishlaydi. Biroq, ularning maqsadi tubdan farq qiladi.

Uch funksiyaning taqqoslanishi

XususiyatwithContextlaunchasync
Yangi korutina yaratadiYo'qHaHa
Natija qaytaradiHa (T to'g'ridan-to'g'ri)Yo'q (Job)Ha (Deferred<T>)
BajarilishiKetma-ketParallelParallel
Natijani kutishAvtomatikjoin()await()
Odatiy foydalanishDispetcher almashtirishFire-and-forgetParallel hisoblashlar

Tanlash qoidasi

Agar fon oqimida bitta operatsiya bajarib natija olish kerak bo'lsa — withContext dan foydalaning. Agar bir nechta mustaqil operatsiyalarni parallel ishga tushirish kerak bo'lsa — async bilan await dan foydalaning. Agar natija kerak bo'lmasa (loglash, kesh yozish) — launch. Google Android arxitekturasida Repository qatlami uchun withContext ni afzal ko'rilgan vosita sifatida tavsiya qiladi.

withContext bilan kod misollari

Kotlin tilida Android ilovalarida withContext dan foydalanishning uchta amaliy stsenariysini ko'rib chiqamiz. Har bir misol aniq vazifa va to'g'ri shablonni ko'rsatadi.

Misol 1: Repository-da tarmoq so'rovi

ViewModel repository usulini Main-dagi korutinadan chaqiradi. Ichida withContext(Dispatchers.IO) HTTP so'rovini bajaradi va natija avtomatik qaytariladi:

kotlin
class UserRepository(
    private val api: UserApi
) {
    suspend fun getUser(id: String): User {
        return withContext(Dispatchers.IO) {
            api.fetchUser(id)
        }
    }
}

ViewModel-dagi korutina getUser ni oddiy to'xtatuvchi funksiya kabi chaqiradi — dispetcherni aniq ko'rsatmasdan. withContext oqimni almashtirish tafsilotlarini yashiradi.

Misol 2: Ikki ketma-ket fon operatsiyasi

Bir nechta IO operatsiyalarini ketma-ket bajarish kerak bo'lganda, withContext ularni yagona blokda birlashtiradi. Bu har bir operatsiyani alohida withContext ga o'rashdan ko'ra samaraliroq:

kotlin
suspend fun loadUserProfile(id: String): Profile {
    return withContext(Dispatchers.IO) {
        val user = api.fetchUser(id)
        val posts = api.fetchPosts(id)
        Profile(user, posts)
    }
}

Ikkala operatsiya Dispatchers.IO da bajariladi va Profile natijasi keraksiz kontekst almashtirishlarsiz yaratilib qaytariladi. Agar operatsiyalar mustaqil bo'lsa, parallel bajarish uchun async dan foydalanish yaxshiroq.

Misol 3: NonCancellable bilan aralash kontekst

Ba'zi stsenariylarda bekor qilib bo'lmaydigan kodni bajarish kerak — masalan, ekran yopilganda holatni saqlash. withContext + NonCancellable kombinatsiyasi bu vazifani hal qiladi:

kotlin
withContext(Dispatchers.IO + NonCancellable) {
    cache.saveState(state)
    analytics.logEvent("state_saved")
}

+ operatori ikkita kontekst elementini birlashtiradi: IO dispetcheri va NonCancellable bayrog'i. Blok ota korutina bekor qilingan taqdirda ham bajariladi — bu yakuniy operatsiyalar uchun foydali.

Ichki mexanizm: Continuation va optimallashtirishlar

withContext ning ichki amalga oshirilishi Continuation mexanizmiga — Kotlin korutinalarining markaziy abstraksiyasiga tayanadi. Har bir to'xtash nuqtasi (suspend point) bajarilish holatini Continuation ob'ektida saqlaydi va withContext bundan mustasno emas.

withContext bayt-kod darajasida kontekstni qanday o'zgartiradi

Kotlin kompilyatori withContext ni kotlinx.coroutines dan withContext metodiga chaqiruv sifatida tarjima qiladi, u ichki qismida yangi DispatchedContinuation namunasini yaratadi. Ushbu ob'ekt asl Continuation ni o'rab oladi va undagi dispetcherni almashtiradi. Agar yangi dispetcher joriydan farq qilsa, bajarilish to'xtatiladi, blok tegishli oqimlar havzasiga yuboriladi va tugagandan so'ng asl kontekst bilan qayta boshlanadi.

Optimallashtirish: kontekstlar mos kelganda fast-path

withContext korutina allaqachon ishlayotgan bir xil dispetcher bilan chaqirilganda, Kotlin fast-path ni ishga soladi: blok sinxron tarzda, DispatchedContinuation yaratmasdan va oqimlar havzasiga jo'natmasdan bajariladi. Bu withContext ni bir xil kontekst bilan takroriy chaqiruvlarda amalda tekin qiladi. JetBrains benchmarklariga ko'ra (kotlinx.coroutines 1.8), fast-path 0,1 mks dan kam vaqtda bajariladi.

Unumdorlik nuqtai nazaridan cheklovlar

Farqli dispetcher bilan har bir withContext chaqiruvi yangi DispatchedContinuation yaratadi va oqimni almashtirishni talab qiladi — bu yukga qarab 1 dan 5 mks gacha vaqt oladi. Ko'pgina ilovalar uchun bu kechikish sezilmaydi, ammo minglab iteratsiyali sikllarda operatsiyalarni bitta withContext blokida to'plash yaxshiroqdir.

withContext dan foydalanishda tipik xatolar

Hatto tajribali dasturchilar ham withContext bilan ishlashda xato qiladilar. Eng keng tarqalgan to'rtta muammo va ularning oldini olish usullarini ko'rib chiqamiz.

Xato 1: Keraksiz ichki withContext

Dasturchilar ko'pincha har bir qatorni alohida withContext ga o'raydilar, operatsiyalarni bir blokda birlashtirish o'rniga. Farqli dispetcher bilan har bir qo'shimcha chaqiruv qo'shimcha yuk yaratadi.

To'g'ri: ketma-ket IO operatsiyalarini bitta withContext(Dispatchers.IO) { ... } blokida birlashtiring. Agar operatsiyalarning bir qismi CPU intensiv bo'lsa — xuddi shu blok ichida withContext(Dispatchers.Default) dan foydalaning.

Xato 2: Parallel vazifalar uchun withContext o'rnida foydalanish

withContext kodni ketma-ket bajaradi. Agar ikkita mustaqil tarmoq so'rovi bitta withContext ga o'ralgan bo'lsa, ular birin-ketin bajariladi. Parallel uchun async + await dan foydalaning.

kotlin
// Ketma-ket — sekin
withContext(Dispatchers.IO) {
    val a = api.fetchA()
    val b = api.fetchB()
}

// Parallel — tez
coroutineScope {
    val a = async { api.fetchA() }
    val b = async { api.fetchB() }
    println("${a.await()} ${b.await()}")
}

Xato 3: Kritik operatsiyalarda NonCancellable ni unutish

withContext vaqtida korutina bekor qilinsa, Dispatchers.IO dagi blok ham to'xtatiladi. Har qanday holatda ham tugatilishi kerak bo'lgan operatsiyalar uchun (ma'lumotlar bazasiga yozish, analitika jo'natish) withContext ni NonCancellable bilan birlashtiring.

Xato 4: IO bloki ichida UI holatini o'zgartirish

Hech qachon View komponentlarini withContext(Dispatchers.IO) ichida yangilamang. withContext butun blok tugaguncha Main ga qaytmaydi. UI yangilashni withContext ning yopuvchi qavsidan keyin bajaring — u holda korutina allaqachon asosiy oqimda bo'ladi.

Ko'p beriladigan savollar

withContext runBlocking dan qanday farq qiladi?

withContext — oqimni bloklamaydigan, balki mavjud korutina ichida kontekstni almashtiradigan to'xtatuvchi funksiya. runBlocking — korutinalar va oddiy kod o'rtasidagi ko'prik bo'lib, joriy oqimni tugaguncha bloklaydi. withContext UI oqimi uchun xavfsiz, runBlocking esa yo'q.

withContext ni suspend bo'lmasdan ishlatish mumkinmi?

Yo'q, withContext to'xtatuvchi funksiyadir, shuning uchun uni faqat boshqa to'xtatuvchi funksiyadan yoki korutinadan (launch/async) chaqirish mumkin. Oddiy funksiyadan withContext chaqirilmaydi — buning uchun runBlocking yoki CoroutineScope kerak.

withContext ga bir xil dispetcherni bersam nima bo'ladi?

Kotlin fast-path ni faollashtiradi — blok bir xil oqimda sinxron tarzda almashtirilmasdan bajariladi. Qo'shimcha yuk 0,1 mks dan kam. Bu xato emas, ammo bunday chaqiruv ortiqcha — kodni withContext siz bajarish yaxshiroq.

withContext istisnolar bilan qanday ishlaydi?

withContext ichidagi istisnolar oddiy koddagidek — try-catch orqali tarqaladi. Agar blok istisno tashlasa, u ota korutinaga tarqaladi va ishlov berilmasa uni bekor qiladi. withContext ichida yoki uning atrofida try-catch dan foydalaning.

withContext yangi korutina yaratadimi?

Yo'q, withContext yangi korutina yaratmaydi. U mavjud korutinadan foydalanadi, lekin vaqtincha uning kontekstini o'zgartiradi. Bu uni launch va async dan farqlaydi, chunki ular bola korutinalar yaratadi. Xatti-harakat kotlinx.coroutines manba kodi bilan tasdiqlangan.

Xulosa

  • withContext — mavjud korutina ichida CoroutineContext ni o'zgartirish uchun to'xtatuvchi funksiya, asl kontekstga avtomatik qaytadi
  • Dispatchers.IO — withContext ichida tarmoq so'rovlari va disk operatsiyalari uchun asosiy dispetcher
  • Fast-path — Kotlin optimallashtirishi, bir xil dispetcher bilan withContext sinxron tarzda qo'shimcha yuksiz bajariladi
  • Parallel vazifalar async/await ni talab qiladi, withContext emas — withContext kodni ketma-ket bajaradi
  • NonCancellable — korutina bekor qilinganda uzilmasligi kerak bo'lgan kritik operatsiyalar uchun bayroq
  • Repository qatlami — Google ko'rsatmalariga ko'ra Android arxitekturasida withContext uchun tavsiya etilgan joy
  • Continuation — Kotlin bayt-kod darajasida withContext da kontekst almashtirishga asoslangan mexanizm

Biz kalit topshirig'i bilan mobil ilovani ishlab chiqamiz

IT Sectr 2017-yildan beri startaplar va korxonalar uchun iOS va Android ilovalarini yaratadi. Biz sizga maslahat beramiz va eng yaxshi yechimni taklif qilamiz.

Loyihani muhokama qilish

Shuningdek o'qing