launch — منشئ Coroutine Builder في Kotlin يبدأ كوروتين دون إرجاع نتيجة، ويعيد كائن Job للتحكم في التنفيذ. ينفذ هذا المنشئ نمط fire-and-forget: يبدأ الكوروتين العمل في خلفية وينتهي تلقائياً. وفقاً لوثائق JetBrains، 2024، فإن launch هو الطريقة الأساسية لتشغيل المهام المتوازية في Kotlin Coroutines.
الخلاصة
launch — دالة امتداد في Kotlin، متاحة عبر استيراد kotlinx.coroutines، تنشئ كوروتين جديداً في CoroutineScope معين. على عكس الدوال العادية، الكود داخل launch يُنفذ بشكل متزامن — يمكن أن يتوقف الكوروتين دون حظر الخيط ويستأنف لاحقاً.
منشئ launch هو لبنة أساسية في نموذج الكوروتينات في Kotlin. لا يُرجع قيمة محسوبة لكنه يُرجع كائن Job يسمح بالتحكم في تنفيذ الكوروتين. جميع الكوروتينات التابعة التي تُطلق عبر launch داخل كوروتين آخر تكون مرتبطة بالأب.
يُعرف منشئ launch كدالة inline بعدة بارامترات: CoroutineScope و CoroutineContext و CoroutineStart و suspend block. البارامترات لها قيم افتراضية، مما يجعل launch ملائماً للسيناريوهات النموذجية.
public fun CoroutineScope.launch(
context: CoroutineContext = EmptyCoroutineContext,
start: CoroutineStart = CoroutineStart.DEFAULT,
block: suspend CoroutineScope.() -> Unit
): Job
البارامتر context يقبل CoroutineContext الذي يجمع بين dispatcher ومعالج استثناءات وعنصر مسمى. غالباً ما يتم تمرير Dispatchers.IO أو Dispatchers.Main أو SupervisorJob لعزل الأخطاء.
Job — الكائن المُعاد الذي يمثل دورة حياة الكوروتين. يمكن أن يكون Job في الحالات: New, Active, Completing, Completed, Cancelling, Cancelled. تعكس كل حالة حالة التنفيذ وتسمح بالتفاعل مع التغييرات.
val job = CoroutineScope(Dispatchers.IO).launch {
repeat(10) { i ->
delay(1000L)
println("التقدم: $i")
}
}
println("الوظيفة نشطة: ${job.isActive}")
delay(2500L)
job.cancel()
println("الوظيفة ملغاة: ${job.isCancelled}")
يدعم Job التسلسل الهرمي: إذا تم إلغاء الكوروتين الأب، يتم إلغاء جميع الكوروتينات التابعة تلقائياً. SupervisorJob يغير هذا السلوك — الكوروتينات التابعة لا تُلغى عندما يفشل أحدها.
التزامن المهيكل يعني أن كل كوروتين يُطلق داخل CoroutineScope محدد، ولا يكتمل النطاق حتى تنهي جميع الكوروتينات التابعة عملها. launch يدعم هذا المبدأ بالكامل — الكوروتينات التي تُطلق داخل كوروتين آخر هي تابعة له.
مع استدعاءات launch المتداخلة، يتشكل شجرة من الكوروتينات. ينتظر الكوروتين الأب اكتمال جميع الكوروتينات التابعة، مما يضمن ترتيب تنفيذ يمكن التنبؤ به ويبسط إدارة الموارد.
fun main() = runBlocking {
launch {
launch {
delay(1000L)
println("اكتمل الطفل 1")
}
launch {
delay(500L)
println("اكتمل الطفل 2")
}
println("جميع الأطفال يكتملون قبل هذا السطر")
}
}
يختلف هذا السلوك عن التزامن القائم على الخيوط، حيث الخيوط التابعة غير مرتبطة بالأب. في الكوروتينات، الأب لا يكتمل حتى تنهي جميع الكوروتينات التابعة عملها.
معالجة الاستثناءات في launch تعتمد على نوع Job. بالنسبة لـ Job العادي، تنتشر الاستثناءات إلى الكوروتين الأب وتلغيه. بالنسبة لـ SupervisorJob أو SupervisorScope، يتم عزل الاستثناءات — خطأ في كوروتين تابع لا يؤثر على الآخرين.
val scope = CoroutineScope(SupervisorJob() + Dispatchers.IO)
scope.launch {
try {
riskyOperation()
} catch (e: Exception) {
println("تم الالتقاط: ${e.message}")
}
}
scope.launch {
println("هذا لا يزال يعمل بفضل SupervisorJob")
}
لمعالجة الاستثناءات غير الملتقطة بشكل عام، يُستخدم CoroutineExceptionHandler. يلتقط الاستثناءات التي لم تتم معالجتها داخل الكوروتين ويسمح بتسجيل الخطأ دون تعطل التطبيق.
في Android، يُستخدم launch في كل مكان: من ViewModel إلى WorkManager. النمط الرئيسي هو استخدام lifecycleScope في Fragment و viewModelScope في ViewModel للإلغاء التلقائي للكوروتينات عند انتهاء دورة حياة المكون.
class ProfileViewModel : ViewModel() {
private val repository = UserRepository()
fun loadProfile(userId: String) {
viewModelScope.launch(Dispatchers.IO) {
val profile = repository.fetchProfile(userId)
withContext(Dispatchers.Main) {
_profileState.update { it.copy(profile = profile) }
}
}
}
}
viewModelScope يلغي الكوروتينات تلقائياً عند تدمير ViewModel. هذا يزيل التسريبات ويضمن أن العمليات الخلفية لا تستمر بعد فقدان السياق. بالإضافة، يمكن استخدام withContext للتبديل بين dispatchers.
الأسئلة الشائعة
launch يُرجع Job ولا يُرجع نتيجة، بينما async يُرجع Deferred<T> للحصول على النتيجة. يُستخدم launch للعمليات من نوع fire-and-forget، و async — عندما تحتاج لانتظار القيمة المُعادة واستخدامها.
استدعِ job.cancel() على كائن Job المحفوظ. للإلغاء الجماعي، ألغِ CoroutineScope بالكامل عبر scope.cancel(). يجب أن يكون الكوروتين متعاوناً — تحقق من isActive أو استخدم دوال suspend قابلة للإلغاء.
استخدم try-catch داخل كتلة launch أو مرر CoroutineExceptionHandler في CoroutineContext. لعزل الأخطاء، استخدم SupervisorJob — عندها خطأ في كوروتين تابع لن يلغي البقية.
لا، launch هي دالة امتداد لـ CoroutineScope. بدون نطاق، لا يمكن للكوروتين اتباع مبدأ التزامن المهيكل. استخدم GlobalScope.launch بحذر — فهو ينشئ كوروتين بدون ارتباط بدورة الحياة.
العدد محدود بمجموعة خيوط dispatcher. Dispatchers.Default يستخدم عدد خيوط يساوي عدد أنوية المعالج. Dispatchers.IO يدعم حتى 64 خيطاً. عند تشغيل عدد أكبر من الكوروتينات، يتم وضعها في طابور.
الملخص
سنقوم بتطوير تطبيق جوال جاهز
تقدم IT Sectr تطبيقات iOS وAndroid للشركات الناشئة والشركات منذ عام 2017. سوف نقدم لك النصح ونقترح أفضل حل.
اقرأ أيضًا