قوائم المهام في Kotlin للمبتدئين: دليل شامل

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

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

ابدأ الدورة

العمل مع قوائم المهام في Kotlin: للمبتدئين

\n

في التطوير الحديث، غالبًا ما تنشأ الحاجة لتنفيذ العديد من المهام بشكل غير متزامن: معالجة التنزيلات، إرسال الطلبات إلى API، العمل مع قواعد البيانات. بدون تنظيم صحيح للكود، قد يؤدي ذلك إلى الفوضى - حيث سيتم تنفيذ المهام بترتيب غير متوقع، وسيتم تحميل موارد النظام بشكل زائد. تعمل قوائم المهام (task queues) على حل هذه المشكلة. في هذه المقالة، سنشرح كيفية إنشاء واستخدام قوائم المهام في Kotlin باستخدام coroutines و Channel. المادة موجهة للمطورين المبتدئين الذين لديهم معرفة أساسية بـ Kotlin.

\n\n

ما هي قائمة المهام ولماذا نحتاجها؟

\n

قائمة المهام هي بنية بيانات تعمل وفق مبدأ FIFO (First In, First Out - "من يدخل أولاً يخرج أولاً"). تقوم بإضافة مهمة إلى نهاية القائمة، ويقوم معالج خاص (worker) باستخراجها من البداية وتنفيذها. هذا يسمح بـ:

\n
    \n
  • تنظيم التنفيذ. المهام لا تتعارض مع بعضها البعض.
  • \n
  • التحكم في الحمل. يمكنك تحديد عدد المهام التي يتم تنفيذها في وقت واحد.
  • \n
  • زيادة استجابة التطبيق. العمليات الثقيلة لا تمنع الخيط الرئيسي.
  • \n
\n

في Kotlin، الأداة الرئيسية للعمل مع القوائم غير المتزامنة هي coroutines ومكونها Channel. هذه خيوط خفيفة الوزن لا تستهلك الكثير من الموارد.

\n\n

إعداد المشروع للعمل مع coroutines

\n

قبل كتابة الكود، تأكد من أن مشروعك يحتوي على التبعيات اللازمة. إذا كنت تستخدم Gradle، أضف إلى ملف build.gradle.kts (أو build.gradle):

\n
dependencies {\n    implementation("org.jetbrains.kotlinx:kotlinx-coroutines-core:1.7.3")\n    implementation("org.jetbrains.kotlinx:kotlinx-coroutines-android:1.7.3") // لنظام Android\n}
\n

الآن أنت مستعد لإنشاء قائمتك الأولى.

\n\n

إنشاء قائمة بسيطة باستخدام Channel

\n

Channel هو في الأساس قائمة جاهزة يمكنها نقل البيانات بين coroutines. لنلق نظرة على مثال أساسي: لدينا منتج (producer) يقوم بتوليد المهام، ومستهلك (consumer) يقوم بتنفيذها.

\n
import kotlinx.coroutines.*\nimport kotlinx.coroutines.channels.Channel\n\nfun main() = runBlocking {\n    val channel = Channel<String>() // إنشاء قناة للنصوص\n\n    // المنتج: يرسل المهام\n    launch {\n        val tasks = listOf("تحميل ملف", "معالجة صورة", "إرسال تقرير")\n        for (task in tasks) {\n            println("تم إرسال المهمة: $task")\n            channel.send(task) // إضافة إلى القائمة\n            delay(500) // محاكاة الوقت بين المهام\n        }\n        channel.close() // إغلاق القناة بعد إرسال جميع المهام\n    }\n\n    // المستهلك: ينفذ المهام\n    launch {\n        for (task in channel) { // قراءة المهام من القائمة\n            println("جارٍ التنفيذ: $task")\n            delay(1000) // محاكاة وقت التنفيذ\n            println("تم الانتهاء: $task")\n        }\n    }\n\n    println("الخيط الرئيسي يواصل العمل...")\n    delay(5000) // انتظار الانتهاء\n}
\n

ماذا يحدث هنا؟

\n
    \n
  • Channel<String>() ينشئ قائمة غير مانعة (non-blocking).
  • \n
  • send() يضيف عنصرًا، for (task in channel) يقرأها بالترتيب.
  • \n
  • تقوم القناة تلقائيًا بحظر coroutine المستهلك إذا كانت القائمة فارغة، والمنتج إذا كانت القائمة ممتلئة (الافتراضي السعة 0، أي rendezvous).
  • \n
\n

سيكون مخرجات البرنامج متسلسلة: يتم تنفيذ المهام واحدة تلو الأخرى بترتيب الإضافة.

\n\n

إدارة عدة عمال (workers) والتخزين المؤقت (buffering)

\n

غالبًا ما تتطلب التطبيقات الحقيقية معالجة متوازية. لنفترض أن لدينا 10 مهام ونريد معالجتها بـ

المدونات

توصيات الكتب