البرمجة غير المتزامنة في Kotlin: دليل شامل

مدرب بايثون أونلاين للمبتدئين

تعلم Python بسهولة دون إرهاق نظري. حل مهام عملية مع التحقق التلقائي واكتب الكود مباشرة في المتصفح.

ابدأ الدورة

البرمجة غير المتزامنة في Kotlin: دليل شامل

البرمجة غير المتزامنة هي نهج تطويري لا يقوم فيه البرنامج بحظر التنفيذ بانتظار اكتمال العمليات الطويلة (مثل طلبات الشبكة، قراءة الملفات، أو العمل مع قاعدة البيانات). بدلاً من ذلك، يستمر في تنفيذ مهام أخرى، ويتم إرجاع النتيجة لاحقاً. في عالم Kotlin، الأداة الرئيسية للعمل غير المتزامن هي الروتينات المتزامنة (coroutines) — وهي خيوط خفيفة الوزن تسمح بكتابة كود غير متزامن بشكل يشبه الكود المتزامن تقريباً.

في هذه المقالة، سنشرح كيفية عمل البرمجة غير المتزامنة في Kotlin، من الأساسيات إلى التقنيات المتقدمة. ستتعلم كيفية استخدام الروتينات المتزامنة بكفاءة، وتجنب الحظر، وكتابة تطبيقات قابلة للتوسع.



1. أساسيات الروتينات المتزامنة في Kotlin

الروتينات المتزامنة هي المفهوم الأساسي للبرمجة غير المتزامنة في Kotlin. إنها تسمح بإيقاف تنفيذ الدالة مؤقتاً دون حظر الخيط. للعمل مع الروتينات المتزامنة، يتم استخدام المكتبة kotlinx.coroutines. إليك مثال بسيط:

import kotlinx.coroutines.*

fun main() = runBlocking { launch { delay(1000L) // تأخير غير حاظر println("العالم!") } println("مرحباً،")}

في هذا الكود، يقوم runBlocking بإنشاء سياق حاظر للروتين المتزامن (يُستخدم عادةً فقط في main أو الاختبارات)، بينما يقوم launch بتشغيل روتين متزامن جديد. الدالة delay هي دالة تعليق (suspend-function) تعمل على إيقاف الروتين المتزامن مؤقتاً دون حظر الخيط.

المفاهيم الأساسية:

  • CoroutineScope — نطاق رؤية الروتينات المتزامنة، يدير دورة حياتها.
  • CoroutineContext — مجموعة من الإعدادات (الموزع، معالج الاستثناءات).
  • دالة التعليق (Suspend-function) — دالة يمكن إيقافها مؤقتاً واستئنافها لاحقاً.


2. دوال التعليق والموزعين

دوال التعليق (Suspend-functions) هي أساس الكود غير المتزامن. يمكنها استدعاء دوال تعليق أخرى (delay, withContext) وإيقاف تنفيذها مؤقتاً. مثال:

suspend fun fetchUserData(): String {    delay(2000L) // محاكاة طلب شبكة    return "بيانات المستخدم"}

fun main() = runBlocking { val data = async { fetchUserData() } println("جارٍ التحميل...") println(data.await()) // انتظار النتيجة}

الموزعون (Dispatchers) يحددون الخيط الذي سينفذ عليه الروتين المتزامن:

  • Dispatchers.Default — للمهام كثيفة الاستخدام لوحدة المعالجة المركزية (الافتراضي).
  • Dispatchers.IO — لعمليات الإدخال والإخراج (الشبكة، الملفات).
  • Dispatchers.Main — لخيط واجهة المستخدم (Android, Swing).
  • Dispatchers.Unconfined — غير مرتبط بخيط معين (نادر الاستخدام).

مثال مع تبديل الموزع:

suspend fun loadData(): String = withContext(Dispatchers.IO) {    // تنفيذ عملية ثقيلة في خيط الخلفية    Thread.sleep(1000L) // محاكاة عملية حاظرة    "النتيجة"}

استخدام الموزع الصحيح أمر بالغ الأهمية للأداء. لا تستخدم Dispatchers.Main للعمليات الطويلة — فهذا سيحظر واجهة المستخدم.



3. العمل مع async/await والقنوات

للتنفيذ المتوازي لمهام متعددة، استخدم async و await. يقوم async بإرجاع كائن Deferred يمكن انتظاره:

fun main() = runBlocking {    val result1 = async(Dispatchers.IO) { fetchFromApi("url1") }    val result2 = async(Dispatchers.IO) { fetchFromApi("url2") }    println("النتيجة 1: ${result1.await()}")    println("النتيجة 2: ${result2.await()}")}

suspend fun fetchFromApi(url: String): String { delay(1000L) return "رد من $url"

المدونات

توصيات الكتب