Jetpack Compose هي مجموعة أدوات تعريفية حديثة لبناء واجهات Android بلغة Kotlin. يصف المطور واجهة المستخدم من خلال دوال composable، وتقوم المجموعة بإعادة رسم الأجزاء المتغيرة فقط تلقائياً. وفقاً لـ Android Developers (2026)، يعمل Jetpack Compose على Android 5.0 (API 21) وما فوق، ويدعم Material Design 3 ويحقق 120 إطاراً في الثانية على الأجهزة متوسطة المدى بفضل نظام Recomposition الخاص به — وهي خوارزمية diff ذكية تقوم بتحديث الأدوات المتغيرة فقط.
أهم النقاط
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 هي وسوم (annotation) تحول دالة Kotlin عادية إلى لبنة بناء لواجهة المستخدم. تصف الدالة Composable كيف يجب أن يبدو جزء من الواجهة — نص، زر، قائمة. بدلاً من إرجاع قيمة، تقوم الدالة بإصدار (emit) مكونات واجهة المستخدم في التركيبة. هذا يشبه المولد: كل دالة تضيف عناصر إلى الشاشة عند استدعائها.
@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.
تستخدم دوال Composable الفتحات بنشاط — trailing lambda، content: @Composable (() -> Unit). هذا يسمح بإنشاء حاويات: Card و Column و Row تقبل لامدا content، ويتم تضمين المحتوى في مكان الفتحة. استبدلت Slot API سمات XML مثل android:layout_gravity — الآن يتم تحديد موضع العناصر الفرعية بكود Kotlin داخل كتلة المحتوى.
الحالة في Compose هي أي قيمة يمكن أن تتغير بمرور الوقت. عندما تتغير الحالة، يقوم Compose بجدولة إعادة التركيبة لجميع المكونات التي تقرأ هذه الحالة. تشبه الآلية React hooks: mutableStateOf يعيد MutableState<T>، وقراءة .value تشترك تلقائياً في التركيبة الحالية للتغييرات.
@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 للحالة المحلية (مثل بطاقة موسعة). هذا الفصل يتبع مبدأ المكونات الذكية/البسيطة.
رفع الحالة هو نمط لنقل الحالة من المكون الفرعي إلى المكون الأصلي. يمرر الأصل القيمة و callback عبر المعاملات، ويستدعي الفرع callback عند التغيير. يحتفظ الأصل بـ mutableStateOf، والفرع فقط بالمعاملات. هذا يجعل المكون قابلاً لإعادة الاستخدام والاختبار: يمكن استخدام نفس TextField مع أي مصدر بيانات.
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). جميع الرسوم المتحركة تعمل على طبقة الرسومات دون التسبب في تركيبة غير ضرورية.
لا يجب أن تقوم دوال Composable بتنفيذ تأثيرات جانبية مباشرة (طلبات الشبكة، الموقتات، الاشتراكات) — حيث يتم استدعاؤها في كل إعادة تركيب، مما سيؤدي إلى طلبات مكررة. للتأثيرات الجانبية، يوفر Compose عائلة من دوال Effect: LaunchedEffect تبدأ coroutine عند الدخول إلى التركيبة وتلغيها عند الخروج، DisposableEffect — للموارد التي تتطلب تنظيفاً صريحاً (أجهزة الاستشعار، BroadcastReceiver).
@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 بتسجيل مستمع وإلغاء الاشتراك عند مغادرة الشاشة — بدون خطر تسرب الذاكرة.
إذا كنت بحاجة إلى تشغيل coroutine ليس عند الدخول إلى التركيبة ولكن عند حدث ما (النقر على زر)، يتم استخدام rememberCoroutineScope(). يعيد CoroutineScope مرتبطاً بدورة حياة Composable، دون الحاجة إلى DisposableEffect. مثال: تشغيل طلب شبكة عند النقر على زر — scope.launch { viewModel.loadData() }.
الاختيار بين Compose و View System هو السؤال المعماري الرئيسي لمطوري Android في 2026. كلتا التقنيتين مدعومتان من Google، لكن Compose هو الاتجاه الرئيسي الذي تستثمر فيه Google مواردها. يتلقى View System فقط الإصلاحات الحرجة ولا يتطور. يظهر الفرق في البنية، وإدارة الحالة، والأداء، ووقت التطوير.
| الجانب | Jetpack Compose | View 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 بفضل بنيته التصريحية والرسوم المتحركة المدمجة.
الأسئلة الشائعة
نعم، عبر ComposeView في تخطيط XML. أضف تبعية Compose ولف الشاشة أو جزءاً منها في ComposeView { MyComposable() }. الترحيل شاشة تلو الأخرى.
السبب هو أن الحالة مرفوعة عالياً جداً أو يتم استخدام كائنات قابلة للتغيير. الحل: derivedStateOf للبيانات المشتقة و remember للمراجع الثابتة.
استخدم LazyColumn (مشابه لـ RecyclerView). يتم إنشاء العناصر وإعادة استخدامها أثناء التمرير. للقوائم المعقدة بأنواع خلايا مختلفة — LazyColumn { items(items, key = { it.id }) { ... } }.
لا، يمكنك البدء مباشرة بـ Compose. تساعد معرفة View System في صيانة الكود القديم، لكن Compose نظام بيئي مستقل بوثائقه وأنماطه الخاصة.
نعم، Material 3 هو السمة القياسية لـ Compose منذ 2023. يتم إضافته عبر implementation("androidx.compose.material3:material3"). يعتبر Material 2 قديماً.
الملخص
سنقوم بتطوير تطبيق جوال جاهز
تقدم IT Sectr تطبيقات iOS وAndroid للشركات الناشئة والشركات منذ عام 2017. سوف نقدم لك النصح ونقترح أفضل حل.