البرمجة التفاعلية في Kotlin: مكتبة kotlinx.coroutines و Flow

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

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

ابدأ الدورة

البرمجة التفاعلية في Kotlin: قوة kotlinx.coroutines و Flow

\n\n

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

\n\n

المفاهيم الأساسية لـ Flow

\n\n

Flow هو تدفق بيانات غير متزامن بارد يصدر القيم بشكل تسلسلي. وهو يدعم:

\n
    \n
  • التدفقات الباردة — يبدأ إنشاء البيانات فقط عند وجود مشترك (عامل تشغيل طرفي).
  • \n
  • سياق التنفيذ — يمكن للتدفق التبديل بين موزعي coroutines مختلفين.
  • \n
  • الإلغاء عبر coroutines — إلغاء coroutine الأصلي ينهي Flow تلقائيًا.
  • \n
\n\n

التثبيت والإعداد

\n

لاستخدام Flow، أضف التبعية في ملف build.gradle.kts:

\n
dependencies {\n    implementation("org.jetbrains.kotlinx:kotlinx-coroutines-core:1.8.1")\n}
\n\n

إنشاء واستهلاك Flow

\n

لننشئ تدفقًا بسيطًا للأرقام مع تأخير:

\n
import kotlinx.coroutines.*\nimport kotlinx.coroutines.flow.*\n\nfun simpleFlow(): Flow<Int> = flow {\n    for (i in 1..5) {\n        delay(100) // محاكاة عمل غير متزامن\n        emit(i)    // إصدار القيمة\n    }\n}\n\nfun main() = runBlocking {\n    simpleFlow().collect { value ->\n        println("تم الاستلام: $value")\n    }\n}
\n

في هذا المثال، يقوم flow { ... } بإنشاء تدفق بارد، و collect هو عامل تشغيل طرفي يبدأ التنفيذ.

\n\n

تحويل البيانات باستخدام عوامل التشغيل

\n

يوفر Flow مجموعة غنية من عوامل التشغيل المشابهة لـ RxJava:

\n
    \n
  • map — يحول كل قيمة.
  • \n
  • filter — يقوم بتصفية القيم بناءً على شرط.
  • \n
  • flatMapConcat — يدمج التدفقات بشكل تسلسلي.
  • \n
  • catch — يعالج الاستثناءات داخل التدفق.
  • \n
\n

مثال مع عوامل التشغيل:

\n
fun transformFlow(): Flow<String> = flow {\n    emit("Kotlin")\n    emit("Java")\n    emit("Python")\n}.map { it.lowercase() }\n .filter { it.startsWith("k") }\n\nfun main() = runBlocking {\n    transformFlow().collect { println(it) }\n    // الإخراج: kotlin\n}
\n\n

معالجة الأخطاء والإكمال

\n

يسمح Flow بمعالجة الاستثناءات بأناقة باستخدام catch وتنفيذ إجراءات الإنهاء عبر onCompletion:

\n
fun errorProneFlow(): Flow<Int> = flow {\n    emit(1)\n    emit(2)\n    throw RuntimeException("خطأ!")\n    emit(3) // لن يتم تنفيذه\n}\n\nfun main() = runBlocking {\n    errorProneFlow()\n        .catch { e -> println("تم التقاط الخطأ: ${e.message}") }\n        .onCompletion { println("تم إنهاء التدفق") }\n        .collect { println(it) }\n}\n// الإخراج: 1, 2, تم التقاط الخطأ: خطأ!, تم إنهاء التدفق
\n\n

التدفقات الساخنة: StateFlow و SharedFlow

\n

على عكس Flow البارد، فإن StateFlow و SharedFlow هما تدفقات ساخنة تخزن الحالة ويمكن أن يكون لهما عدة مشتركين.

\n\n

StateFlow

\n

يُستخدم لتخزين ومراقبة الحالة (على سبيل المثال، في ViewModel):

\n
class CounterViewModel {\n    private val _counter = MutableStateFlow(0)\n    val counter: StateFlow<Int> = _counter.asStateFlow()\n\n    fun increment() {\n        _counter.value++\n    }\n}\n\n// في Activity أو Fragment\nlifecycleScope.launch {\n    viewModel.counter.collect { value ->\n        textView.text = "العداد: $value"\n    }\n}
\n\n

SharedFlow

\n

مناسب لـ

توصيات