Jetpack Compose: ما هو، المفاهيم الأساسية ووظائف Composable

المؤلف: IT Sectr نُشر: 2026-05-01 وقت القراءة: 9 دق

Jetpack Compose هي مجموعة أدوات تعريفية حديثة لبناء واجهات Android بلغة Kotlin. يصف المطور واجهة المستخدم من خلال دوال composable، وتقوم المجموعة بإعادة رسم الأجزاء المتغيرة فقط تلقائياً. وفقاً لـ Android Developers (2026)، يعمل Jetpack Compose على Android 5.0 (API 21) وما فوق، ويدعم Material Design 3 ويحقق 120 إطاراً في الثانية على الأجهزة متوسطة المدى بفضل نظام Recomposition الخاص به — وهي خوارزمية diff ذكية تقوم بتحديث الأدوات المتغيرة فقط.

أهم النقاط

  • Jetpack Compose — إطار عمل واجهة مستخدم تصريحي لنظام Android حيث يتم بناء الواجهة من خلال دوال @Composable في Kotlin.
  • Recomposition — آلية تقوم بتحديث المكونات التي تغيرت بياناتها فقط تلقائياً، مما يوفر 120 إطاراً في الثانية.
  • State تتم إدارته عبر mutableStateOf و collectAsState و StateFlow — عند تغيير القيمة، تعاد التركيبة للعروض التابعة.
  • Modifier — سلسلة من الدوال لتكوين الهوامش والأحجام والخلفية والنقرات والرسوم المتحركة دون وراثة الفئات.
  • Side Effects — LaunchedEffect و DisposableEffect و rememberCoroutineScope — تدير الإجراءات الجانبية: الموقتات وطلبات الشبكة والاشتراكات.

ما هو Jetpack Compose؟

Jetpack Compose هو إطار عمل تصريحي من Google لبناء واجهات مستخدم Android، تم الإعلان عنه في 2019 ووصل إلى الإصدار المستقر في 2021. على عكس View System القديم (تخطيط XML + Activity/Fragment)، يستخدم Compose دوال Kotlin الموسومة — @Composable. يتم وصف الواجهة بالكامل بلغة Kotlin: لا يوجد فصل بين XML والكود. هذا ألغى فئة الأخطاء المتعلقة بعدم تطابق المعرفات في XML و Kotlin (لم يكن type-safe synthetic مفيداً في إعادة الهيكلة).

تم بناء Compose على نظام العرض الخاص به — Canvas، غير المرتبط بتسلسل View الهرمي. كل Composable يرسم نفسه مباشرة على Canvas، متجاوزاً onMeasure/onDraw في View System. وهذا يوفر زيادة في الأداء على الشاشات المعقدة: في اختبارات Google (2023)، تم عرض شاشة Compose بـ 200 عنصر أسرع بنسبة 40% من شاشة مماثلة على RecyclerView + ViewHolder.

الحد الأدنى من المتطلبات والتوافق

يتطلب Compose minSdk 21 (Android 5.0) و Kotlin 1.9+. يقوم BOM (Bill of Materials) الخاص بـ Compose بمزامنة إصدارات جميع مكتبات Compose. الإطار متوافق مع الكود الحالي لـ View System: يتم تضمين Compose عبر ComposeView في تخطيطات XML، والعروض القديمة عبر AndroidView في تسلسل Compose الهرمي. وفقاً لـ Google Play Console (2025)، يغطي Android 5.0+ 97% من الأجهزة النشطة، لذا فإن التوافق ليس قيداً لمعظم المشاريع.

دوال Composable والتركيبة

@Composable هي وسوم (annotation) تحول دالة Kotlin عادية إلى لبنة بناء لواجهة المستخدم. تصف الدالة Composable كيف يجب أن يبدو جزء من الواجهة — نص، زر، قائمة. بدلاً من إرجاع قيمة، تقوم الدالة بإصدار (emit) مكونات واجهة المستخدم في التركيبة. هذا يشبه المولد: كل دالة تضيف عناصر إلى الشاشة عند استدعائها.

kotlin
@Composable
fun ProfileCard(name: String, avatarUrl: String) {
    Card(
        modifier = Modifier.fillMaxWidth().padding(16.dp),
        colors = CardDefaults.cardColors(
            containerColor = MaterialTheme.colorScheme.surface
        )
    ) {
        Row(verticalAlignment = Alignment.CenterVertically) {
            AsyncImage(
                model = avatarUrl,
                contentDescription = "الصورة الرمزية",
                modifier = Modifier.size(48.dp).clip(CircleShape)
            )
            Spacer(Modifier.width(12.dp))
            Text(
                text = name,
                style = MaterialTheme.typography.titleMedium
            )
        }
    }
}

تأخذ الدالة ProfileCard معاملات (name, avatarUrl) وتصدر Card → Row → AsyncImage + Text. التركيبة هي شجرة المكونات المصدرة في تمريرة واحدة. إذا لم تتغير المعاملات، يتخطى Compose استدعاء الدالة (recomposition skip). إذا تغير name فقط، فسيتم استدعاء Text فقط، ولن يتم إعادة رسم باقي العناصر. هذا التركيبة الذكية هي ميزة الأداء الرئيسية لـ Compose مقارنة بالتحسين اليدوي في View System.

الفتحات (Slots) و Content Lambda

تستخدم دوال Composable الفتحات بنشاط — trailing lambda، content: @Composable (() -> Unit). هذا يسمح بإنشاء حاويات: Card و Column و Row تقبل لامدا content، ويتم تضمين المحتوى في مكان الفتحة. استبدلت Slot API سمات XML مثل android:layout_gravity — الآن يتم تحديد موضع العناصر الفرعية بكود Kotlin داخل كتلة المحتوى.

إدارة الحالة في Compose

الحالة في Compose هي أي قيمة يمكن أن تتغير بمرور الوقت. عندما تتغير الحالة، يقوم Compose بجدولة إعادة التركيبة لجميع المكونات التي تقرأ هذه الحالة. تشبه الآلية React hooks: mutableStateOf يعيد MutableState<T>، وقراءة .value تشترك تلقائياً في التركيبة الحالية للتغييرات.

kotlin
@Composable
fun CounterExample() {
    var count by remember { mutableStateOf(0) }

    Column(modifier = Modifier.padding(16.dp)) {
        Text("تم النقر: $count")
        Button(onClick = { count++ }) {
            Text("زيادة")
        }
    }
}

@Composable
fun UserScreen(viewModel: UserViewModel) {
    val userName by viewModel.userName.collectAsState()
    Text("المستخدم: $userName")
}

remember يحافظ على القيمة بين عمليات إعادة التركيبة — وإلا فسيتم إنشاء mutableStateOf من جديد عند كل تحديث لواجهة المستخدم. collectAsState() يحول StateFlow من ViewModel إلى حالة متوافقة مع Compose. التوصية — استخدام ViewModel مع StateFlow لحالة مستوى الشاشة، و mutableStateOf للحالة المحلية (مثل بطاقة موسعة). هذا الفصل يتبع مبدأ المكونات الذكية/البسيطة.

رفع الحالة (State Hoisting)

رفع الحالة هو نمط لنقل الحالة من المكون الفرعي إلى المكون الأصلي. يمرر الأصل القيمة و callback عبر المعاملات، ويستدعي الفرع callback عند التغيير. يحتفظ الأصل بـ mutableStateOf، والفرع فقط بالمعاملات. هذا يجعل المكون قابلاً لإعادة الاستخدام والاختبار: يمكن استخدام نفس TextField مع أي مصدر بيانات.

Modifier — تخصيص المظهر

Modifier هو كائن يصف تحويلات Composable: الحجم، الهوامش، الخلفية، معالجة النقرات، الرسوم المتحركة، التمرير. يتم تطبيق المعدلات عبر سلسلة استدعاءات: Modifier.fillMaxWidth().padding(16.dp).background(Color.Blue).clickable { }. كل استدعاء يعيد Modifier جديدة مع الخاصية المضافة — بدون تغيير الكائن الأصلي.

ترتيب المعدلات مهم. Modifier.padding(16.dp).background(Color.Blue) يلون المنطقة مع هامش. Modifier.background(Color.Blue).padding(16.dp) يلون المستطيل الداخلي، ويبقى الهامش شفافاً. الآلية تشبه نموذج صندوق CSS: padding أولاً → background يعمل مثل margin + background؛ background أولاً → padding يعمل مثل background + هامش داخلي. يكفي للمطور أن يتذكر: padding أولاً = هامش خارجي، padding لاحقاً = هامش داخلي.

المعدلات المخصصة

إذا لم تكن المعدلات المضمنة كافية، يتم إنشاء معدل مخصص عبر Modifier.composed { ... } أو Modifier.then(). داخل المعدل المخصص، يمكن استخدام قياسات التخطيط (Modifier.layout { measurable, constraints -> ... }) والرسم (Modifier.drawWithContent { ... }) والإيماءات (Modifier.pointerInput { ... }). مثال: معدل لرسوم متحركة نابضة عند النقر — يقيس الحجم، وعند النقر يبدأ رسماً متحركاً للقياس عبر animateFloatAsState.

للرسوم المتحركة، يوفر Compose animate*AsState (animateFloatAsState, animateColorAsState, animateDpAsState) — يتم تحريك القيم بين الحالة القديمة والجديدة عند التغيير. لرسوم الدخول/الخروج — AnimatedVisibility و AnimatedContent مع انتقالات مدمجة (fade, slide, expand). جميع الرسوم المتحركة تعمل على طبقة الرسومات دون التسبب في تركيبة غير ضرورية.

Side Effects: LaunchedEffect و DisposableEffect و remember

لا يجب أن تقوم دوال Composable بتنفيذ تأثيرات جانبية مباشرة (طلبات الشبكة، الموقتات، الاشتراكات) — حيث يتم استدعاؤها في كل إعادة تركيب، مما سيؤدي إلى طلبات مكررة. للتأثيرات الجانبية، يوفر Compose عائلة من دوال Effect: LaunchedEffect تبدأ coroutine عند الدخول إلى التركيبة وتلغيها عند الخروج، DisposableEffect — للموارد التي تتطلب تنظيفاً صريحاً (أجهزة الاستشعار، BroadcastReceiver).

kotlin
@Composable
fun SensorReader() {
    val context = LocalContext.current
    var sensorValue by remember { mutableStateOf(0f) }

    DisposableEffect(Unit) {
        val sensor = registerSensorListener(context) { value ->
            sensorValue = value
        }
        onDispose {
            unregisterSensorListener(sensor)
        }
    }

    Text("القيمة: $sensorValue")
}

@Composable
fun UserGreeting(userId: String) {
    LaunchedEffect(userId) {
        val profile = api.fetchProfile(userId)
        // تحديث الحالة
    }
}

LaunchedEffect(userId) يعاد تشغيله إذا تغير userId — يتم إلغاء coroutine السابقة وتبدأ جديدة مع userId الجديد. هذا يلغي الحاجة إلى إدارة إلغاء الطلبات يدوياً. DisposableEffect(Unit) — تأثير بمفتاح ثابت Unit، يتم تشغيله عند الدخول إلى التركيبة ويستدعي onDispose عند الخروج. يقوم SensorReader بتسجيل مستمع وإلغاء الاشتراك عند مغادرة الشاشة — بدون خطر تسرب الذاكرة.

rememberCoroutineScope

إذا كنت بحاجة إلى تشغيل coroutine ليس عند الدخول إلى التركيبة ولكن عند حدث ما (النقر على زر)، يتم استخدام rememberCoroutineScope(). يعيد CoroutineScope مرتبطاً بدورة حياة Composable، دون الحاجة إلى DisposableEffect. مثال: تشغيل طلب شبكة عند النقر على زر — scope.launch { viewModel.loadData() }.

Jetpack Compose مقابل View System: مقارنة

الاختيار بين Compose و View System هو السؤال المعماري الرئيسي لمطوري Android في 2026. كلتا التقنيتين مدعومتان من Google، لكن Compose هو الاتجاه الرئيسي الذي تستثمر فيه Google مواردها. يتلقى View System فقط الإصلاحات الحرجة ولا يتطور. يظهر الفرق في البنية، وإدارة الحالة، والأداء، ووقت التطوير.

الجانبJetpack ComposeView System
وصف واجهة المستخدمدوال Kotlin @Composableتخطيط XML + Activity/Fragment
الحالةmutableStateOf, StateFlow, إعادة رسم تلقائيfindViewById, يدوي: setText, notifyDataSetChanged
الأداءإعادة تركيب ذكية، عرض Canvasتسلسل View الهرمي، measure/layout/draw
الرسوم المتحركةanimate*AsState, AnimatedVisibility, مدمجةValueAnimator, ObjectAnimator, Transition
التوافقminSdk 21, جسور ComposeView/AndroidViewجميع الإصدارات، أي
حجم APK+3–5 ميغابايت لـ Composeبدون تكلفة إضافية

للمشاريع الجديدة، توصي Google باستخدام Jetpack Compuse كمعيار لتطوير واجهة المستخدم. يبقى View System لصيانة الكود المكتوب قبل 2021، والحالات التي يكون فيها الحجم الأدنى لـ APK حرجاً (مثل الأسواق الناشئة بأجهزة المستوى الأساسي). Compose يقلل حجم كود واجهة المستخدم بنسبة 30–50% مقارنة بـ View System بفضل بنيته التصريحية والرسوم المتحركة المدمجة.

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

هل يمكن استخدام Compose في مشروع قائم على View System؟

نعم، عبر ComposeView في تخطيط XML. أضف تبعية Compose ولف الشاشة أو جزءاً منها في ComposeView { MyComposable() }. الترحيل شاشة تلو الأخرى.

لماذا يتم إعادة رسم Composable الخاص بي بشكل متكرر؟

السبب هو أن الحالة مرفوعة عالياً جداً أو يتم استخدام كائنات قابلة للتغيير. الحل: derivedStateOf للبيانات المشتقة و remember للمراجع الثابتة.

كيفية تنفيذ قائمة في Compose؟

استخدم LazyColumn (مشابه لـ RecyclerView). يتم إنشاء العناصر وإعادة استخدامها أثناء التمرير. للقوائم المعقدة بأنواع خلايا مختلفة — LazyColumn { items(items, key = { it.id }) { ... } }.

هل أحتاج إلى تعلم View System قبل Compose؟

لا، يمكنك البدء مباشرة بـ Compose. تساعد معرفة View System في صيانة الكود القديم، لكن Compose نظام بيئي مستقل بوثائقه وأنماطه الخاصة.

هل يدعم Compose Material 3؟

نعم، Material 3 هو السمة القياسية لـ Compose منذ 2023. يتم إضافته عبر implementation("androidx.compose.material3:material3"). يعتبر Material 2 قديماً.

الملخص

  • Jetpack Compose — إطار عمل واجهة مستخدم تصريحي لنظام Android حيث تتم كتابة الواجهة بالكامل بلغة Kotlin من خلال دوال @Composable.
  • Recomposition يعيد رسم المكونات المتغيرة فقط تلقائياً، مما يوفر 120 إطاراً في الثانية بدون تحسين يدوي.
  • State تتم إدارته عبر mutableStateOf و collectAsState و StateFlow؛ نمط State Hoisting يجعل المكونات قابلة لإعادة الاستخدام.
  • Modifier — سلسلة تحويلات لتكوين المظهر والرسوم المتحركة والسلوك دون وراثة الفئات.
  • Side Effects (LaunchedEffect, DisposableEffect) تعزل الإجراءات الجانبية عن إعادة التركيب، مما يمنع التسريبات والطلبات المكررة.
  • LazyColumn يحل محل RecyclerView بكود أقل، و AnimatedVisibility تحل محل سلاسل Animator المعقدة.
  • توصي Google Compose لجميع المشاريع الجديدة؛ يبقى View System لصيانة الكود القديم والحالات التي يكون فيها الحجم الأدنى لـ APK حرجاً.

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

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

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

اقرأ أيضًا