Coroutine Builder: چیست، انواع سازنده‌های کوروتین و چگونه کار می‌کنند

نویسنده: IT Sectr منتشر شده: 2026-06-21 زمان مطالعه: 8 دقیقه

Coroutine Builder — توابع Kotlin Coroutines هستند که کوروتین‌ها را ایجاد و اجرا می‌کنند و نحوه اجرای آنها را تعیین می‌کنند. سازنده‌های launch، async، runBlocking و produce سناریوهای مختلفی را پوشش می‌دهند: از وظایف پس‌زمینه تا محاسبات موازی با بازگشت نتیجه. به گفته JetBrains, 2024، Coroutine Builder اساس مدل کوروتین است و همزمانی ساختاریافته و مدیریت چرخه عمر را فراهم می‌کند.

نکات اصلی

  • Coroutine Builder — تابعی که یک کوروتین در CoroutineScope مشخص ایجاد می‌کند
  • launch — کوروتین را بدون بازگشت نتیجه اجرا می‌کند، شی Job را برمی‌گرداند
  • async — کوروتین را با بازگشت Deferred اجرا می‌کند و امکان دریافت نتیجه از طریق await() را فراهم می‌کند
  • runBlocking — رشته جاری را مسدود می‌کند، به عنوان پل بین کد blocking و suspending استفاده می‌شود
  • produce — کوروتین با کانال برای انتقال جریانی داده ایجاد می‌کند (به نفع Flow منسوخ شده)

Coroutine Builder چیست؟

Coroutine Builder — تابع توسعه‌ای Kotlin است که CoroutineScope و suspend-block را می‌پذیرد و یک کوروتین جدید ایجاد و اجرا می‌کند. هر سازنده تعیین می‌کند که کوروتین چگونه اجرا شود: با بازگشت نتیجه یا بدون آن، با مسدود کردن رشته یا به صورت ناهمگام. سازنده‌ها نقاط ورود به مدل کوروتین در زبان هستند.

همه سازنده‌ها از طریق CoroutineScope کار می‌کنند که چرخه عمر کوروتین‌های فرزند را مدیریت می‌کند. هنگام لغو scope، تمام کوروتین‌های اجرا شده از طریق آن به طور خودکار لغو می‌شوند — این اصل همزمانی ساختاریافته است. این رویکرد از نشت کوروتین‌ها جلوگیری می‌کند و پایان‌پذیری قابل پیش‌بینی را تضمین می‌کند.

kotlin
import kotlinx.coroutines.*

fun main() = runBlocking {
    // سازنده‌ها در داخل CoroutineScope کار می‌کنند
    val job = launch {
        delay(1000L)
        println("جهان!")
    }
    println("سلام،")
    job.join()
}

انواع اصلی سازنده‌های کوروتین

Kotlin چهار سازنده داخلی کوروتین ارائه می‌دهد: launch، async، runBlocking و produce. هر کدام نوع بازگشتی و حوزه کاربرد خود را دارند. برای توسعه موبایل Android، اصلی‌ترین آنها launch و async هستند — آنها به صورت غیرمسدودکننده کار می‌کنند و با اجزای معماری ادغام می‌شوند.

سازندهنوع بازگشتیمسدود کردن رشتهسناریو
launchJobخیروظایف fire-and-forget
asyncDeferred<T>خیرمحاسبات موازی
runBlockingTبلهتست‌ها، تابع main
produceReceiveChannel<E>خیرانتقال جریانی (deprecated)

هر سازنده پارامترهای اضافی می‌پذیرد: CoroutineStart (استراتژی اجرا)، CoroutineContext (توزیع‌کننده، استثناها) و بلوک کد نام‌گذاری شده. به طور پیش‌فرض کوروتین بلافاصله اجرا می‌شود (CoroutineStart.DEFAULT).

launch: اجرای fire-and-forget

launch — پرکاربردترین سازنده در توسعه Android است. کوروتینی را اجرا می‌کند که نتیجه برنمی‌گرداند و شی Job را برای مدیریت چرخه عمر آن برمی‌گرداند. این انتخاب ایده‌آل برای عملیاتی است که فقط به اثر جانبی نیاز دارند: ذخیره در پایگاه داده، ارسال تحلیل، به‌روزرسانی UI.

سینتکس و استفاده از launch

سازنده launch CoroutineScope، CoroutineContext اختیاری و suspend-block را می‌پذیرد. Job بازگشتی به شما اجازه می‌دهد کوروتین را لغو کنید، منتظر اتمام آن بمانید یا وضعیت آن را بررسی کنید.

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

پارامتر CoroutineStart.LAZY اجرا را تا فراخوانی صریح start() یا join() به تأخیر می‌اندازد. این برای مقداردهی اولیه تأخیری و اجرای شرطی مفید است. برای اجرای فوری استاندارد از CoroutineStart.DEFAULT استفاده می‌شود یا پارامتر حذف می‌گردد.

async: محاسبات موازی با نتیجه

async — سازنده‌ای که Deferred<T> را برمی‌گرداند — وعده ناهمگام نتیجه. فراخوانی await() کوروتین را تا دریافت نتیجه متوقف می‌کند، بدون اینکه رشته را مسدود کند. این مکانیزم اصلی برای وظایف موازی در کوروتین‌های Kotlin است.

اجرای دو درخواست به صورت موازی

async به ویژه زمانی مؤثر است که نیاز به انجام چندین عملیات مستقل به طور همزمان باشد. برخلاف فراخوانی ترتیبی توابع suspend، async کوروتین‌ها را به صورت موازی اجرا می‌کند و زمان کل اجرا را کاهش می‌دهد.

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 از Job ارث‌بری می‌کند، بنابراین async از تمام عملیات چرخه عمر پشتیبانی می‌کند: لغو، انتظار برای اتمام، مدیریت استثناها. هنگام لغو scope، کوروتین‌های فرزند Deferred به طور خودکار لغو می‌شوند.

runBlocking: پل به دنیای blocking

runBlocking — تنها سازنده‌ای است که رشته جاری را تا پایان کوروتین مسدود می‌کند. CoroutineScope جدیدی ایجاد می‌کند و کوروتین ارسال شده را اجرا می‌کند و رشته فراخوان را مسدود می‌کند. در نقاط ورود main()، در تست‌ها و در ادغام با کد blocking استفاده می‌شود.

چه زمانی runBlocking ضروری است

runBlocking در سه سناریو توجیه می‌شود: نقطه ورود برنامه (main)، تست‌های واحد توابع suspend و ادغام با کتابخانه‌های callback-based که در آنها نمی‌توان از suspend استفاده کرد. در کد تولید Android، استفاده از runBlocking در رشته اصلی قطعاً توصیه نمی‌شود.

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

برای تست‌ها توصیه می‌شود به جای runBlocking از kotlinx-coroutines-test با TestCoroutineDispatcher استفاده کنید — این کنترل زمان را فراهم می‌کند و از قفل‌شدگی در محیط تست جلوگیری می‌کند.

چگونه سازنده مناسب را انتخاب کنیم

انتخاب Coroutine Builder به نتیجه بازگشتی و سناریوی اجرا بستگی دارد. اگر عملیات نیاز به بازگشت داده ندارد — از launch استفاده کنید. اگر نتیجه عملیات ناهمگام مورد نیاز است — async. runBlocking را فقط برای bridging به کار ببرید و produce را برای جریان‌های واکنشی با Flow جایگزین کنید.

توصیه‌های عملی برای Android

در پروژه‌های Android با Kotlin Coroutines، جفت اصلی سازنده‌ها launch و async هستند. launch در ViewModel و UseCases برای اجرای کوروتین‌ها استفاده می‌شود و async — برای درخواست‌های موازی به شبکه یا پایگاه داده. کتابخانه‌های مدرن (Ktor, Room) قبلاً از توابع suspend پشتیبانی می‌کنند که نیاز به استفاده مستقیم از async را به حداقل می‌رساند.

  • launch — برای fire-and-forget (ثبت رویداد، تحلیل، ذخیره‌سازی موقت)
  • async — برای درخواست‌های موازی با ترکیب نتایج
  • runBlocking — فقط در main() و تست‌ها (نه در production روی Main-thread)
  • produce — با Flow / SharedFlow / StateFlow جایگزین کنید

سوالات متداول

تفاوت launch و async در Kotlin چیست؟

launch Job برمی‌گرداند و نتیجه اجرا را برنمی‌گرداند، در حالی که async Deferred<T> — شیئی که می‌توان از طریق await() نتیجه را از آن دریافت کرد — برمی‌گرداند. launch برای عملیات fire-and-forget استفاده می‌شود، async — برای وظایفی که داده برمی‌گردانند.

آیا می‌توان از runBlocking در Android Activity استفاده کرد؟

توصیه نمی‌شود. runBlocking در رشته اصلی باعث ANR می‌شود و UI را مسدود می‌کند. از lifecycleScope.launch در داخل Activity و Fragment استفاده کنید — این راه‌حل داخلی بدون قفل‌شدگی است.

سازنده launch چه چیزی برمی‌گرداند؟

سازنده launch شی Job را برمی‌گرداند که به شما امکان می‌دهد چرخه عمر کوروتین را کنترل کنید: لغو (cancel)، انتظار برای اتمام (join)، بررسی وضعیت (isActive, isCompleted, isCancelled).

Deferred در Kotlin Coroutines چیست؟

Deferred<T> — وعده ناهمگام نتیجه است که توسط سازنده async بازگردانده می‌شود. از Job ارث‌بری می‌کند و متدهای await() برای دریافت نتیجه، getCompleted() برای دسترسی غیرمسدودکننده و getCompletionExceptionOrNull() برای بررسی استثنا را اضافه می‌کند.

چگونه launch را با تأخیر اجرا کنیم؟

از پارامتر CoroutineStart.LAZY استفاده کنید: scope.launch(start = CoroutineStart.LAZY) { ... }. سپس برای اجرای واقعی job.start() یا job.join() را فراخوانی کنید. این برای مقداردهی اولیه تأخیری و اجرای شرطی کوروتین‌ها مفید است.

خلاصه

  • Coroutine Builder — تابع ایجاد کوروتین که نحوه اجرا و نوع بازگشتی آن را تعیین می‌کند
  • launch — سازنده اصلی برای وظایف بدون بازگشت نتیجه، Job را برای مدیریت کوروتین برمی‌گرداند
  • async — سازنده برای محاسبات موازی، Deferred با قابلیت await() نتیجه را برمی‌گرداند
  • runBlocking — سازنده مسدودکننده برای main() و تست‌ها، در رشته اصلی Android توصیه نمی‌شود
  • همزمانی ساختاریافته لغو خودکار کوروتین‌های فرزند را هنگام لغو scope تضمین می‌کند
  • produce منسوخ شده است — برای جریان‌های داده واکنشی از Flow، SharedFlow یا StateFlow استفاده کنید
  • انتخاب سازنده به سناریو بستگی دارد: fire-and-forget → launch، داده‌های موازی → async، bridging → runBlocking

ما یک اپلیکیشن موبایل به صورت کلید در دست توسعه خواهیم داد

IT Sectr از سال 2017 برنامه‌های iOS و Android را برای استارتاپ‌ها و کسب‌وکارها ایجاد می‌کند. ما به شما مشاوره می‌دهیم و بهترین راه‌حل را پیشنهاد خواهیم کرد.

بحث درباره پروژه

همچنین بخوانید