suspend / launch / async
الكوروتينات suspend / launch / async
الكوروتينات طريقة Kotlin الخفيفة للبرمجة غير المتزامنة بكود يبدو متسلسلًا بدل تعقيد الخيوط والـ callbacks.
دالة suspend يمكن إيقافها واستئنافها دون حجز الخيط (thread) الذي تعمل عليه — بخلاف Thread.sleep الذي يحجزه فعليًّا. launch تبدأ كوروتين في الخلفية دون انتظار نتيجة (fire-and-forget). async تبدأ كوروتين يُرجع نتيجة عبر Deferred، تُستخرج لاحقًا بـ await(). كلاهما يحتاج نطاق تنفيذ (CoroutineScope) مثل runBlocking أو viewModelScope في أندرويد.
الصياغة
suspend fun الاسم(...): نوع { ... }
launch { /* بلا نتيجة */ }
val d = async { /* يُرجع نتيجة */ }
d.await()📄 مثال
import kotlinx.coroutines.*
suspend fun fetchUser(id: Int): String {
delay(500) // انتظار غير محظور للخيط
return "مستخدم #$id"
}
fun main() = runBlocking {
launch { println(fetchUser(1)) } // خلفية، بلا انتظار نتيجة هنا
val a = async { fetchUser(2) }
val b = async { fetchUser(3) }
println("${a.await()} و ${b.await()}") // ينفّذان بالتوازي
}أهم النقاط
| العنصر | الوظيفة |
|---|---|
| suspend fun | دالة قابلة للإيقاف دون حجز الخيط، تُستدعى من كوروتين أو دالة suspend أخرى |
| delay() | انتظار غير محظور — بديل Thread.sleep داخل دوال suspend |
| launch { } | يبدأ كوروتين بلا نتيجة مُرجَعة |
| async { } | يبدأ كوروتين يُرجع Deferred؛ نتيجته تُستخرج عبر await() |
💡 نصائح عملية
- استخدم async فقط عند الحاجة لنتيجة متوازية من عدة عمليات؛ launch كافية للمهام الجانبية
- في أندرويد، استخدم النطاق المناسب (viewModelScope/lifecycleScope) بدل GlobalScope لتفادي تسريب الذاكرة
⚠️ أخطاء شائعة
- استدعاء دالة suspend مباشرة من دالة عادية (غير suspend) خارج نطاق كوروتين — خطأ ترجمة
- استخدام Thread.sleep داخل كوروتين بدل delay — يحجز الخيط فعليًّا ويلغي فائدة الكوروتينات
خصائص ذات صلة
🎓 تريد فهم الصورة الكاملة خطوة بخطوة؟ ابدأ من مسار KOTLIN الكامل بالعربي.