@Composable: ما هي، تعليق Compose التوضيحي ونطاق التطبيق

المؤلف: IT Sectr نُشر: 2026-06-27 وقت القراءة: 8 دق

التعليق التوضيحي @Composable هو عنصر أساسي في Jetpack Compose يحول دالة Kotlin العادية إلى لبنة بناء تصريحية لواجهة المستخدم. بدون هذا التعليق التوضيحي، من المستحيل إنشاء أي شاشة في تطوير Android الحديث. وفقًا لـ Google Android Developers, 2026، أكثر من 80% من المشاريع الجديدة على Kotlin تستخدم Compose لبناء واجهة المستخدم، و @Composable هو التعليق التوضيحي الأكثر استخدامًا في النظام البيئي.

النقاط الرئيسية

  • @Composable — تعليق توضيحي في Kotlin يسمح للدالة بوصف واجهة المستخدم بشكل تصريحي
  • دوال Composable يمكنها فقط استدعاء دوال Composable أخرى، مع احترام سياق التركيب
  • إعادة التشغيل لدوال Composable يحدث عند تغيير معلمات الإدخال أو الحالة
  • ترتيب الاستدعاء لدوال Composable غير مضمون — Compose يحسن إعادة بناء واجهة المستخدم
  • التسمية لدوال Composable تتبع قاعدة PascalCase، مثل أي مكونات في Compose

ما هو @Composable في Jetpack Compose

@Composable هو تعليق توضيحي للغة Kotlin يحدد دالة على أنها مخصصة لوصف واجهة المستخدم في إطار عمل Jetpack Compose. عندما يواجه مترجم Kotlin هذا التعليق التوضيحي، يقوم بتوليد كود إضافي يسمح للدالة بالعمل في سياق التركيب — نظام إدارة شجرة واجهة المستخدم.

تم تقديم التعليق التوضيحي @Composable من قبل Google في عام 2021 مع أول إصدار مستقر من Jetpack Compose 1.0. قبل ظهوره، كان تطوير واجهات Android يتم حصريًا عبر ترميز XML ونظام View. غير @Composable النهج جذريًا: بدلاً من وصف واجهة المستخدم في ملف ترميز منفصل، يكتب المطور الواجهة مباشرة في Kotlin.

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

الآلية الداخلية لـ @Composable تعتمد على مفهوم الفتحة — منطقة ذاكرة خاصة يتم تخصيصها لكل دالة ضمن التركيب. تخزن هذه الفتحة القيم التي تم تمريرها إلى الدالة، بالإضافة إلى المعلومات الخدمية اللازمة للمقارنة في الاستدعاءات اللاحقة.

كيفية تعريف دالة Composable

لتعريف دالة Composable، يكفي إضافة التعليق التوضيحي @Composable قبل الكلمة المفتاحية fun. يجب أن تكون الدالة في حزمة تستورد التعليق التوضيحي من androidx.compose.runtime. يُوصى بكتابة اسم الدالة بحرف كبير — هذه اتفاقية مقبولة على نطاق واسع في مجتمع Compose تميز بصريًا مكونات واجهة المستخدم عن الدوال العادية.

kotlin
import androidx.compose.runtime.Composable

@Composable
fun Greeting(name: String) {
    var count by remember { mutableStateOf(0) }
    Column {
        Text("مرحبًا، $name!")
        Button(onClick = { count++ }) {
            Text("تم النقر $count مرة")
        }
    }
}

يمكن أن تكون معاملات دالة Composable أي شيء — أنواع بدائية، سلاسل نصية، لامبدا، وحتى دوال Composable أخرى يتم تمريرها عبر Slot API. يُوصى بجعل المعاملات غير قابلة للتغيير (val) لتجنب الآثار الجانبية أثناء إعادة التركيب. يجب إدارة جميع البيانات القابلة للتغيير عبر آليات الحالة في Compose.

لا يمكن لدوال Composable إرجاع قيم عشوائية مثل الدوال العادية — مهمتها الوحيدة هي بناء أو تحديث جزء من شجرة واجهة المستخدم. ومع ذلك، توجد أنماط خاصة مثل State Hoisting، حيث تقبل دالة Compose الحالة والاستدعاءات عبر المعاملات، وتبقى نقية وقابلة لإعادة الاستخدام.

قواعد دوال Composable في Kotlin

يفرض نظام Compose عدة قيود صارمة على كيفية ظهور وسلوك دوال Composable. القاعدة الأولى: دالة Composable يمكنها فقط استدعاء دوال Composable أخرى أو دوال عادية ليس لها آثار جانبية. هذا يضمن قابلية التنبؤ بالتركيب والعمل الصحيح لتحسينات Compose.

القاعدة الثانية تتعلق بترتيب التنفيذ. يحق لـ Compose استدعاء دوال Composable بأي ترتيب، لذلك لا يجب أن يعتمد الكود في جسم هذه الدالة على تسلسل استدعاء الدوال المجاورة. يجب أن تكون كل دالة Composable مكتفية ذاتيًا على مستوى موقعها في شجرة واجهة المستخدم.

القاعدة الثالثة — حظر الآثار الجانبية داخل جسم دالة Composable. العمليات مثل الكتابة في قاعدة البيانات، إرسال طلبات الشبكة، أو تغيير المتغيرات الخارجية يجب أن تتم فقط داخل تأثيرات خاصة: LaunchedEffect، DisposableEffect، أو SideEffect. انتهاك هذه القاعدة يؤدي إلى سلوك غير متوقع أثناء إعادة التركيب.

القاعدة الرابعة: يجب أن تكون دوال Composable عديمة التأثير. استدعاؤها مرة أخرى بنفس الوسائط يجب أن ينتج نفس واجهة المستخدم. هذا الشرط ضروري للعمل الصحيح لتحسين التخطي، حيث يتخطى Compose إعادة رسم الدوال التي لم تتغير بيانات إدخالها.

kotlin
// صحيح: دالة Composable نقية بدون آثار جانبية
@Composable
fun UserCard(user: User, onClick: () -> Unit) {
    Card(modifier = Modifier.clickable { onClick() }) {
        Text(text = user.name)
    }
}

// خطأ: أثر جانبي داخل الجسم
@Composable
fun WrongCard(userId: String) {
    // val result = viewModel.loadUser(userId)  // غير مسموح
    Text("جارٍ التحميل...")
}

أمثلة على استخدام @Composable

لنلق نظرة على مثال عملي لإنشاء شاشة ملف شخصي باستخدام التعليق التوضيحي @Composable. هنا نوضح دمج دوال Composable متعددة، والعمل مع الحالة والمعدلات — العناصر الأساسية لأي تخطيط Compose.

kotlin
@Composable
fun ProfileScreen(userId: String) {
    var isFollowed by remember { mutableStateOf(false) }

    Column(modifier = Modifier.fillMaxSize().padding(16.dp)) {
        ProfileHeader(userId = userId)
        Spacer(modifier = Modifier.height(16.dp))
        StatsRow(posts = 42, followers = 1280)
        Spacer(modifier = Modifier.height(24.dp))
        FollowButton(
            isFollowed = isFollowed,
            onToggle = { isFollowed = !isFollowed }
        )
    }
}

@Composable
fun ProfileHeader(userId: String) {
    Row(verticalAlignment = Alignment.CenterVertically) {
        AsyncImage(model = "https://example.com/avatars/$userId",
            contentDescription = "User avatar")
        Spacer(modifier = Modifier.width(12.dp))
        Text(text = "المستخدم #$userId", style = MaterialTheme.typography.headlineMedium)
    }
}

@Composable
fun StatsRow(posts: Int, followers: Int) {
    Row(modifier = Modifier.fillMaxWidth(), horizontalArrangement = Arrangement.SpaceEvenly) {
        StatItem("Posts", posts)
        StatItem("Followers", followers)
    }
}

@Composable
fun StatItem(label: String, value: Int) {
    Column(horizontalAlignment = Alignment.CenterHorizontally) {
        Text(text = "$value", style = MaterialTheme.typography.headlineSmall)
        Text(text = label, style = MaterialTheme.typography.bodySmall)
    }
}

في المثال، كل دالة Composable مسؤولة عن جزءها الخاص من الشاشة: ProfileScreen يدير الحالة العامة وتركيب الدوال التابعة، ProfileHeader يعرض الصورة الرمزية والاسم، و StatsRow يعرض كتلة الإحصائيات. هذا النهج يتبع مبدأ المسؤولية الفردية ويبسط إعادة استخدام المكونات.

أنواع دوال Composable والغرض منها

في Jetpack Compose، هناك ثلاثة أنواع رئيسية من دوال Composable. النوع الأول — الحاويات (Row, Column, Box, LazyColumn) — تحدد تخطيط العناصر التابعة. النوع الثاني — عناصر العرض (Text, Image, Icon, Button) — تعرض مكونات واجهة مستخدم محددة. النوع الثالث — دوال Composable المخصصة — تجمع المكونات المدمجة في كتل قابلة لإعادة الاستخدام.

تختلف الحاويات عن العناصر العادية في أنها تقبل لامبدا content — المعامل الأخير من النوع @Composable () -> Unit. هذه الآلية تسمح ببناء أشجار واجهة مستخدم متداخلة: كل حاوية تنشئ تركيبًا تابعًا بسياقه الخاص ومنطقة الذاكرة الخاصة به.

تنقسم دوال Composable المخصصة إلى نوعين فرعيين: ذكية (smart) و بسيطة (dumb). الدوال الذكية تدير الحالة والمنطق — تحتوي على استدعاءات remember و LaunchedEffect و APIs أخرى في Compose. الدوال البسيطة تستقبل جميع البيانات عبر المعاملات وتعرضها فقط. فصل المكونات الذكية عن البسيطة يحسن قابلية الاختبار وإعادة استخدام الكود.

النوعمثالالغرض
حاويةColumn, Row, Boxإدارة تخطيط العناصر التابعة
عنصرText, Image, Buttonعرض المحتوى ومعالجة الإدخال
مخصصProfileCard, UserListدمج المكونات القياسية

@Composable وإعادة استخدام المكونات

الميزة الرئيسية للتعليق التوضيحي @Composable هي القدرة على إنشاء مكونات واجهة مستخدم قابلة لإعادة الاستخدام دون وراثة أو تسلسلات هرمية معقدة للفئات. على عكس نظام View، حيث كان كل عنصر مخصص يتطلب إنشاء فئة Java مع منشئات، المكون Composable هو مجرد دالة Kotlin مع معاملات.

لضمان إعادة الاستخدام، يتم استخدام نمط Slot API، حيث تقبل دالة Composable لامبدات content لمناطق مختلفة من تخطيطها. على سبيل المثال، مكون Card يمكنه قبول محتوى منفصل للرأس والجسم والتذييل، مما يجعله عالميًا لأي شاشة في التطبيق.

تلعب المعدلات (Modifier) دورًا رئيسيًا في إعادة الاستخدام: تسمح بتكوين الهوامش والأحجام والنقرات والرسوم المتحركة دون تغيير المكون نفسه. يُوصى دائمًا بتمرير Modifier كمعامل لدالة Composable بقيمة افتراضية: Modifier = Modifier — هذه ممارسة قياسية معتمدة في المكتبات الرسمية من Google.

kotlin
@Composable
fun SectionCard(
    modifier: Modifier = Modifier,
    title: String,
    content: @Composable () -> Unit
) {
    Card(modifier = modifier) {
        Column(modifier = Modifier.padding(16.dp)) {
            Text(text = title, style = MaterialTheme.typography.titleMedium)
            Spacer(modifier = Modifier.height(8.dp))
            content()
        }
    }
}

بفضل Slot API، يمكن استخدام مكون SectionCard على شاشات مختلفة بمحتوى مختلف — نماذج، قوائم، كتل نصية. دمج المعدلات مع Slot API يجعل مكونات Compose مرنة للغاية دون فقدان أمان الأنواع الذي يوفره Kotlin.

الأسئلة الشائعة

ما الفرق بين @Composable ودالة Kotlin العادية؟

دالة @Composable يتم تنفيذها في سياق التركيب ويمكنها قراءة الحالة، وإعادة التشغيل تلقائيًا عند تغيرها. دوال Kotlin العادية لا تملك access إلى آليات تتبع الحالة ولا تشارك في بناء شجرة واجهة المستخدم.

هل يمكن استدعاء دالة Composable من دالة عادية؟

لا، دوال Composable يمكن استدعاؤها فقط من دوال Composable أخرى، لأنها تتطلب سياق تركيب خاص. لدمج كود Compose مع Kotlin العادي، يتم استخدام طريقة setContent { } في Activity أو ComposeView في نظام View.

لماذا تكتب دوال Composable بحرف كبير؟

هذه اتفاقية تسمية معتمدة في مجتمع Compose. الحرف الكبير يميز بصريًا مكونات واجهة المستخدم عن الدوال العادية، متبعًا قواعد تسمية الفئات. ليس هذا مطلبًا من المترجم، ولكنه ممارسة موصى بها في توثيق Google.

كم عدد دوال Composable التي يمكن أن تكون على شاشة واحدة؟

لا توجد حدود على العدد. عمليًا، شاشة كبيرة يمكن أن تحتوي على 50–100 دالة Composable، بما في ذلك المكونات المدمجة (Text, Button) والمخصصة. Compose يحسن شجرة الدوال وينفذ فقط تلك التي تغيرت بيانات إدخالها.

هل يمكن لدالة Composable إرجاع قيمة؟

عادةً ما ترجع دوال Composable Unit، لأن مهمتها بناء واجهة المستخدم. ومع ذلك، توجد دوال متخصصة مثل remember و derivedStateOf الموسومة بـ @Composable والتي ترجع قيمًا. هذا استثناء وليس قاعدة.

الخلاصة

  • @Composable — تعليق توضيحي لوصف واجهة المستخدم بشكل تصريحي في Jetpack Compose
  • دوال Composable تُستدعى فقط داخل دوال Composable أخرى في سياق خاص
  • عدم التأثير — كل تنفيذ متكرر بنفس الوسائط ينتج نفس واجهة المستخدم
  • الآثار الجانبية ممنوعة في جسم الدالة — فقط عبر LaunchedEffect و SideEffect
  • Slot API و Modifier يضمنان إعادة استخدام المكونات دون وراثة
  • دوال الحاوية (Row, Column, LazyColumn) تقبل لامبدات content للعناصر المتداخلة
  • توصية: تمرير Modifier كمعامل لكل دالة Composable مخصصة بقيمة افتراضية

سنقوم بتطوير تطبيق جوال جاهز

تقدم IT Sectr تطبيقات iOS وAndroid للشركات الناشئة والشركات منذ عام 2017. سوف نقدم لك النصح ونقترح أفضل حل.

مناقشة المشروع

اقرأ أيضًا