سلام، امروز میخوام یه تقلبنامه (Cheat Sheet) از Coroutine ها در کاتلین رو باهاتون به اشتراک بذارم که می تونید یه جا ذخیره نگهش دارید هر موقع شک کردید کدوم مورد لازمتون میشه یه نگاه بهش بندازید. Coroutineها یکی از اون مباحث جذاب و در عین حال چالشبرانگیز کاتلین هستن که یادگیریشون میتونه سطح برنامهنویسی شما رو چند پله بالاتر ببره.
Coroutine چیست؟
به زبون ساده، Coroutine ها یه جورایی تردهای (Thread) سبکوزن هستن که برای برنامهنویسی ناهمزمان (Asynchronous) و همزمان (Concurrent) در کاتلین استفاده میشن. با استفاده از Coroutines میتونید تسکهای زمانبر مثل عملیات شبکه یا کار با دیتابیس رو بدون اینکه ترد اصلی (Main Thread) اپلیکیشن مسدود بشه، اجرا کنید. اینطوری اپلیکیشن شما همیشه روان و پاسخگو باقی میمونه.
🔹 کلمات کلیدی و بیلدرهای اصلی
در جدول زیر، کلمات کلیدی و بیلدرهای اصلی Coroutine ها رو به همراه توضیحاتشون میبینید:
| کلمه کلیدی / بیلدر | توضیحات |
|---|---|
suspend | این کلمه کلیدی، یک تابع رو به عنوان تابعی علامتگذاری میکنه که میتونه متوقف بشه و بعداً از سر گرفته بشه. |
launch | یک Coroutine رو شروع میکنه که نتیجهای برنمیگردونه. |
async | یک Coroutine رو شروع میکنه که یک نتیجه از نوع *Deferred برمیگردونه. |
await() | منتظر نتیجه یک Coroutine از نوع async میمونه. |
withContext() | زمینه (Context) اجرای Coroutine رو تغییر میده (مثلاً از Main به IO). |
runBlocking | یک Coroutine مسدودکننده (Blocking) رو شروع میکنه (معمولاً برای تستنویسی استفاده میشه). |
coroutineScope | یک Scope جدید ایجاد میکنه که منتظر تموم شدن همه فرزندانش میمونه. |
supervisorScope | شبیه به coroutineScope هست با این تفاوت که خطا در یکی از فرزندان، باعث لغو شدن بقیه فرزندان نمیشه. |
delay() | یک تابع suspend برای ایجاد تأخیر بدون مسدود کردن ترد. |
yield() | اجرا رو به طور موقت به Coroutines دیگه واگذار میکنه. |
Deferred چیست؟
یک Deferred در واقع یک تعهد برای ارائه یک نتیجه در آینده است. وقتی شما یک کار را با async شروع میکنید، بلافاصله یک شی Deferred دریافت میکنید. این شی به شما اجازه میدهد که بعداً با فراخوانی تابع await() روی آن، منتظر بمانید تا کار تمام شود و نتیجه نهایی را تحویل بگیرید، بدون اینکه در این مدت ترد فعلی مسدود شود.
🔹 Dispatcher ها
Dispatcherها مشخص میکنن که یک Coroutine روی کدوم ترد (Thread) اجرا بشه. در جدول زیر، انواع Dispatchers رو میبینید:
| Dispatcher | کاربرد |
|---|---|
Dispatchers.Main | برای عملیات مربوط به رابط کاربری (UI) (ترد اصلی). |
Dispatchers.IO | برای تسکهای ورودی/خروجی (I/O) مثل کار با شبکه، دیتابیس و فایلها. |
Dispatchers.Default | برای کارهای سنگین و محاسباتی (CPU-intensive). |
Dispatchers.Unconfined | در ترد فعلی اجرا میشه (برای موارد پیشرفته). |
🔹 مثال ۱: استفاده ساده از launch
import kotlinx.coroutines.*
fun main() = runBlocking {
launch {
delay(1000)
println("World!")
}
println("Hello,")
}
خروجی:
Hello,
World!
🔹 مثال ۲: استفاده از async/await
import kotlinx.coroutines.*
suspend fun fetchUser(): String {
delay(1000)
return "Esfandune"
}
suspend fun fetchPosts(): List<String> {
delay(1000)
return listOf("Post 1", "Post 2")
}
fun main() = runBlocking {
val user = async { fetchUser() }
val posts = async { fetchPosts() }
println("User: ${user.await()}, Posts: ${posts.await()}")
}
خروجی:
User: Esfandune, Posts: [Post 1, Post 2]
🔹 مثال ۳: استفاده از withContext
import kotlinx.coroutines.*
suspend fun loadUserData() = withContext(Dispatchers.IO) {
// کارهای پسزمینه در اینجا انجام میشه
"User data loaded"
}
fun main() = runBlocking {
val result = loadUserData()
println(result)
}
خروجی:
User data loaded
🔹 اصول اولیه Flow
Flow در کاتلین برای کار با جریانهای داده (Data Streams) به صورت ناهمزمان استفاده میشه.
import kotlinx.coroutines.*
import kotlinx.coroutines.flow.*
fun numbersFlow(): Flow<Int> = flow {
for (i in 1..3) {
emit(i)
delay(100)
}
}
fun main() = runBlocking {
numbersFlow()
.map { it * 2 }
.collect { println(it) }
}
خروجی:
2
4
6
امیدوارم این مقاله کوتاه و ساده براتون مفید باشه. اگه سوالی راجع کوروتین ها در برنامه نویسی اندروید یا کاتلین مولتی پلتفرم داشتید، می تونید همینجا یا داخل گروه تلگرامی اسفندونه مطرح کنید.


دیدگاهتان را بنویسید