لماذا تحتاج هذا الآن
\nتخيل: أنت تكتب تطبيقًا، وتحتاج إلى عرض إشعار للمستخدم بعد 5 ثوانٍ من الضغط على زر. أو تنفيذ طلب إلى الخادم بعد ثانيتين فقط من انتهاء المستخدم من كتابة النص. أو ببساطة إنشاء رسم متحرك جميل مع تأخير. بدون معرفة كيفية استدعاء دالة مع تأخير في Kotlin — لا يمكنك المضي قدمًا.
\nهذا السؤال هو واحد من أكثر الأسئلة شيوعًا على Stack Overflow (آلاف المشاهدات!)، وليس بدون سبب. في Kotlin هناك 4 طرق كاملة لعمل استدعاء مؤجل، وكل منها مناسب لموقف معين. في هذه المقالة، سنشرحها جميعًا: من delay() البسيط في coroutines إلى Handler الكلاسيكي لنظام Android. ستعرف أي طريقة تختار ولماذا، والأهم من ذلك — سترى كودًا عمليًا يمكنك نسخه فورًا إلى مشروعك.
الطريقة 1: Coroutines و delay() (حديثة ومفضلة)
\nهذه هي الطريقة الأكثر أناقة وموصى بها في Kotlin الحديث. Coroutines هي خيوط خفيفة لا تمنع الخيط الرئيسي. طريقة delay() توقف coroutine مؤقتًا للوقت المحدد، ثم تستأنفها.
للعمل مع coroutines، تحتاج إلى إضافة التبعية في build.gradle.kts:
implementation("org.jetbrains.kotlinx:kotlinx-coroutines-core:1.8.0")\nوإليك كيف يبدو ذلك في الكود:
\nimport kotlinx.coroutines.*\n\nfun main() = runBlocking {\n println("البداية: ${System.currentTimeMillis()}")\n\n // تشغيل coroutine مع تأخير\n launch {\n delay(3000L) // انتظر 3 ثوانٍ\n println("مرت 3 ثوانٍ: ${System.currentTimeMillis()}")\n myDelayedFunction() // استدعاء الدالة المطلوبة\n }\n\n println("ننتظر... (سيتم تنفيذ هذا فورًا)")\n}\n\nfun myDelayedFunction() {\n println("تم تنفيذ الدالة!")}\n\nهام: delay() هي دالة إيقاف مؤقت (suspend function). يمكن استدعاؤها فقط داخل coroutine أو دالة suspend أخرى. إذا حاولت استدعاء delay() خارج coroutine، فسيصدر المترجم خطأ.
كيفية عمل استدعاء مؤجل في Android باستخدام coroutines
\nفي تطوير Android، تعتبر coroutines المعيار الفعلي. إليك مثال لـ Activity:
\nimport androidx.appcompat.app.AppCompatActivity\nimport android.os.Bundle\nimport kotlinx.coroutines.*\n\nclass MainActivity : AppCompatActivity() {\n\n private val scope = CoroutineScope(Dispatchers.Main + SupervisorJob())\n\n override fun onCreate(savedInstanceState: Bundle?) {\n super.onCreate(savedInstanceState)\n setContentView(R.layout.activity_main)\n\n // بعد ثانيتين، عرض رسالة Toast\n scope.launch {\n delay(2000L)\n showToast("مرت ثانيتان!")\n }\n }\n\n private fun showToast(message: String) {\n android.widget.Toast.makeText(this, message, android.widget.Toast.LENGTH_SHORT).show()\n }\n\n override fun onDestroy() {\n super.onDestroy()\n scope.cancel() // إلغاء جميع المهام عند تدمير Activity\n }\n}\nلاحظ: نستخدم Dispatchers.Main للعمل مع واجهة المستخدم. وتأكد من إلغاء scope في onDestroy() لتجنب تسرب الذاكرة.
الطريقة 2: Handler و postDelayed() (كلاسيك Android)
\nإذا كنت تكتب لتطبيق Android ولا تريد (أو لا تستطيع) استخدام coroutines، فإن Handler القديم الجيد لا يزال يعمل. كانت هذه الطريقة شائعة قبل عصر coroutines.
import android.os.Bundle\nimport android.os.Handler\nimport android.os.Looper\nimport androidx.appcompat.app.AppCompatActivity\n\nclass MainActivity : AppCompatActivity() {\n\n private val handler = Handler(Looper.getMainLooper())\n\n override fun onCreate(savedInstanceState: Bundle?) {\n super.onCreate(savedInstanceState)\n setContentView(R.layout.activity_main)