Jetpack Compose هو إطار عمل واجهة مستخدم تعريفي حديث من Google لتطوير Android، تم إصداره في النسخة المستقرة 1.0 في يوليو 2021. يستبدل Compose تخطيط XML الأمرّي ونظام View بدوال Kotlin مع التعليق التوضيحي @Composable. وفقًا لـ Google I/O (2025)، يُستخدم Compose في 55% من المشاريع الجديدة على Android، وينخفض متوسط حجم كود UI بنسبة 30–50% مقارنة بـ XML. يقوم الإطار بإعادة رسم الأجزاء المتغيرة فقط من الشاشة تلقائيًا عند تغيير State، مما يلغي الحاجة إلى استدعاءات notifyDataSetChanged أو findViewById اليدوية.
النقاط الرئيسية
Jetpack Compose هو إطار عمل واجهة مستخدم من Google مبني على مبادئ البرمجة التفاعلية. بدلاً من Activity مع تخطيط XML و FragmentManager و ViewBinding، يصف المطور الواجهة من خلال دوال Kotlin مع التعليق التوضيحي @Composable. لا يستخدم Compose LayoutInflater — واجهة المستخدم هي دوال Kotlin نقية تُترجم إلى bytecode. يتكون الإطار من عدة مكتبات: Compose UI (المكونات الأساسية Text, Button, Column, Row)، Compose Foundation (Material Design, Gestures, Focus)، Compose Material3 (Material You مع Dynamic Colors) و Compose Runtime (State, Side Effects, Coroutines). يعمل Compose على Android API 21+ (Android 5.0) ومتوافق تمامًا مع كود View/XML الموجود من خلال ComposeView — محوّل AndroidView.
View System (2008) يستخدم تسلسلاً هرميًا لكائنات View مع إدارة يدوية: ينشئ المطور تخطيط XML، ويجد Views عبر findViewById، وينفذ Adapter لـ RecyclerView ويستدعي notifyDataSetChanged عند تغيير البيانات. يصف Compose واجهة المستخدم وظيفيًا: عندما تتغير الحالة، يعيد الإطار تشغيل (recompose) دوال Composable المتغيرة فقط، ويحسب الفرق (diff) ويطبق الحد الأدنى من التغييرات على Canvas. أداء Compose مشابه لـ View System، وفي سيناريوهات القوائم المعقدة (LazyColumn) غالبًا ما يتفوق على RecyclerView بفضل تخطي العناصر غير الضرورية عبر معامل key. في IT Sectr، يُستخدم Compose للوحدات الجديدة من تطبيقات Android مع minSdk 24+.
@Composable — تعليق توضيحي يحول دالة Kotlin عادية إلى لبنة بناء لواجهة المستخدم. يمكن لدوال Composable استدعاء دوال Composable أخرى، لتكوين شجرة من المكونات. على عكس View، دوال Composable ليس لها حالة افتراضيًا — فهي عديمة الحالة (stateless) وتُعاد رسمها مع كل تغيير في معاملات الإدخال أو State. يقوم Compose Compiler بتحويل دوال @Composable إلى كود يمكن مقاطعته واستئنافه (positional memoization) — مما يسمح لـ Compose بإعادة تشغيل الأجزاء المتغيرة فقط دون إعادة بناء الشجرة بالكامل.
import androidx.compose.foundation.layout.*
import androidx.compose.material3.*
import androidx.compose.runtime.*
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.unit.dp
@Composable
fun UserProfile(name: String, avatarUrl: String) {
Row(
modifier = Modifier
.fillMaxWidth()
.padding(16.dp),
verticalAlignment = Alignment.CenterVertically
) {
AsyncImage(
model = avatarUrl,
contentDescription = "User avatar",
modifier = Modifier.size(48.dp)
)
Spacer(modifier = Modifier.width(12.dp))
Text(
text = name,
style = MaterialTheme.typography.titleMedium
)
}
}تستقبل الدالة UserProfile name و avatarUrl كمعاملات، وتبني صفًا مع صورة رمزية واسم. Modifier.fillMaxWidth() يمدد المكون عبر العرض بالكامل، .padding(16.dp) يضيف حشوة. يستخدم MaterialTheme.typography.titleMedium نمط النظام Material 3. عندما تتغير معاملات name أو avatarUrl، يعيد Compose تشغيل UserProfile — إعادة إنشاء المكون بقيم جديدة.
State في Compose هو أي قيمة يؤدي تغييرها إلى إعادة التركيب (إعادة تشغيل) دوال @Composable المعتمدة. الطريقة الأساسية هي mutableStateOf()، التي تنشئ MutableState<T> مع دعم نظام snapshot في Compose. Snapshot هي آلية تتبع التغييرات: عند كتابة State، يضع Compose علامة على Snapshot الحالي كـ dirty، ويقوم مُجدوِل إعادة التركيب بإعادة تشغيل دوال Composable التي تقرأ هذا State فقط. للمجموعات القابلة للمراقبة استخدم mutableStateListOf() و mutableStateMapOf(). يدعم Compose State من مكونات Lifecycle-Aware عبر collectAsState() لـ Kotlin Flow و observeAsState() لـ LiveData.
@Composable
fun LikeButton() {
var liked by remember { mutableStateOf(false) }
var count by remember { mutableStateOf(42) }
Button(
onClick = {
liked = !liked
if (liked) count++ else count--
},
colors = ButtonDefaults.buttonColors(
containerColor = if (liked) MaterialTheme.colorScheme.primary
else MaterialTheme.colorScheme.surfaceVariant
)
) {
Text("♥ $count")
}
}ينشئ الكود زر "Like" مع حالة liked (Boolean) و count (Int) مخزنتين عبر mutableStateOf(). عند الضغط، يتم عكس liked ويزداد/ينقص العداد — يقوم Compose تلقائيًا بإعادة تشغيل LikeButton. يسمح المفوض by باستخدام State كمتغير عادي: liked = !liked بدلاً من liked.value = !liked.value. يتغير لون الزر تفاعليًا بين primary (تم الإعجاب) و surfaceVariant (لم يتم الإعجاب).
remember — دالة Compose تخزن قيمة مؤقتًا بين عمليات إعادة التركيب. بدون remember، كل إعادة تشغيل لدالة Composable تنشئ حالة جديدة (mutableStateOf) — وهذا يعطل منطق التطبيق: عند تدوير الشاشة أو تغيير State الأب، يتم إعادة تعيين العداد. تقبل remember تعبير lambda للحساب وتحسب القيمة فقط في أول تركيب؛ في المرات التالية تعيد النتيجة المخزنة مؤقتًا. لإعادة تعيين التخزين المؤقت استخدم remember(key) — يحدد المفتاح متى يُعاد حساب القيمة. remember(key1, key2) يعيد الحساب عند تغيير أي مفتاح. للحالات طويلة العمر (التي تتحمل تدوير الشاشة) استخدم rememberSaveable — شبيه remember مع الحفظ في Bundle عبر SavedStateHandle.
@Composable
fun TimerScreen() {
var seconds by rememberSaveable { mutableStateOf(0) }
LaunchedEffect(Unit) {
while (true) {
delay(1000)
seconds++
}
}
Column(
modifier = Modifier.fillMaxSize().padding(32.dp),
horizontalAlignment = Alignment.CenterHorizontally
) {
Text(
text = "Elapsed: ${seconds}s",
style = MaterialTheme.typography.displayMedium
)
}
}rememberSaveable يحتفظ بـ seconds عند تدوير الشاشة (تغيير الإعدادات). يقوم LaunchedEffect بتشغيل coroutine يزيد seconds كل ثانية. عند إعادة تركيب TimerScreen (كل ثانية) لا يتم إعادة تعيين seconds بفضل rememberSaveable. استخدم remember العادي للحالة التي لا يجب أن تتحمل تغييرات الإعدادات (مثلاً، أعلام الرسوم المتحركة).
Modifier — كائن حاوية غير قابل للتغيير يطبق نمط Builder لتكوين مظهر وسلوك وتخطيط مكونات Composable. كل استدعاء لطريقة Modifier (.padding(), .width(), .clickable(), .background()) يعيد Modifier جديد مع العنصر المضاف. ترتيب المعدّلات مهم: .padding(16.dp).clickable { } — تُطبق الحشوة قبل معالج النقر، clickable يتتبع المساحة بأكملها بما في ذلك الحشوة. .clickable { }.padding(16.dp) — المساحة بأكملها قبل الحشوة قابلة للنقر، الحشوة تزيح المحتوى للداخل. يدعم Modifier التطبيقات المخصصة عبر then(otherModifier) و compositionLocal للوصول إلى إعدادات الأب.
@Composable
fun CardExample() {
Card(
modifier = Modifier
.fillMaxWidth()
.padding(16.dp)
.clickable { println("Card clicked") },
elevation = CardDefaults.cardElevation(defaultElevation = 4.dp),
colors = CardDefaults.cardColors(
containerColor = MaterialTheme.colorScheme.surfaceVariant
)
) {
Column(modifier = Modifier.padding(16.dp)) {
Text("Jetpack Compose", style = MaterialTheme.typography.titleLarge)
Spacer(modifier = Modifier.height(8.dp))
Text(
"UI تعريفية لنظام Android مع State و Modifier",
style = MaterialTheme.typography.bodyMedium
)
}
}
}يُظهر CardExample سلسلة Modifier: fillMaxWidth + padding + clickable. Card هو مكون Material3 مع إعدادات elevation و colors خاصة به. يحتوي Column المتداخل على حشوة داخلية 16dp. يقوم Compose Material3 بتكييف الألوان تلقائيًا مع Dynamic Color (Material You) على Android 12+. Card هو واحد من أكثر من 30 مكون Material3 مدمج في Compose.
State hoisting — نمط رفع الحالة من دالة Composable إلى المستدعي، مما يجعل الدالة عديمة الحالة (stateless). المكون عديم الحالة يستقبل البيانات واستدعاءات回调 عبر المعاملات دون امتلاك State بنفسه. هذا يحسن قابلية إعادة الاستخدام والاختبار: يمكن استدعاء المكون مع States مختلفة واختباره في preview. توصي Google بالهندسة: ViewModel + StateFlow (أو MutableStateFlow) + collectAsState() في Compose. يرفع ViewModel الحالة إلى مستوى الشاشة، ويقوم Compose بعرضها. تعالج التأثيرات الجانبية (LaunchedEffect, DisposableEffect) الأحداث لمرة واحدة.
| المكون | المسؤولية | التقنية |
|---|---|---|
| ViewModel | تخزين الحالة، منطق الأعمال | StateFlow, MutableStateFlow |
| Screen Composable | تنظيم الشاشة، رفع الحالة | collectAsState(), Scaffold, LazyColumn |
| Stateless Component | واجهة مستخدم بدون حالة، عرض نقي | معاملات @Composable + lambdas |
| Side Effect | إجراءات لمرة واحدة (snackbar, تنقل) | LaunchedEffect, SnackbarHostState |
الأسئلة الشائعة
تخطيط XML أمري: LayoutInflater يحمّل XML، findViewById يجد Views، المطور يحدّث النص/القوائم يدويًا. Compose تعريفي: توصف واجهة المستخدم بدوال Kotlin @Composable، ويعيد الإطار رسم الأجزاء المتغيرة فقط تلقائيًا عند تغيير State. يقلل Compose حجم كود UI بنسبة 30–50% ولا يستخدم XML.
نعم، توفر Google Navigation Compose — مكتبة للتنقل التعريفي بين الشاشات. يدير NavController مكدس المسارات، يسجّل composable() الشاشات، يمرّر navArgument المعاملات. البدائل: Voyager (community) و Decompose (Badoo). Navigation Compose هو المعيار الرسمي مع دعم deep links والوسيطات type-safe.
Modifier هو حاوية غير قابلة للتغيير لأنماط الزخرفة (padding, size, clickable, background, border, clip) تُطبّق على مكونات Composable. كل استدعاء يعيد Modifier جديد مع العنصر المضاف. الترتيب مهم: .padding().clickable() يطبق الحشوة قبل النقر، .clickable().padding() — العكس. Modifier هو الطريقة الأساسية لتخصيص مكونات Compose.
يدعم Jetpack Compose Android API 21+ (Android 5.0 Lollipop) من خلال Compose Compiler و Compose BOM. Material 3 (Dynamic Colors) متاح على Android 12+؛ على الإصدارات الأقدم تُستخدم لوحة fallback. للمشاريع الجديدة، توصي Google بـ minSdk 24+ (Android 7.0)، وهو مغطى بالكامل بواسطة Compose.
توفر Google Compose UI Test — مكتبة للاختبار على JVM (سطح المكتب) والمحاكي. الوظائف الرئيسية: composeTestRule.setContent { } لعرض المكون، onNodeWithText() للبحث عن العناصر، performClick()/performTextInput() للإجراءات. اختبارات Espresso متوافقة مع Compose عبر ComposeTestRule، لكن Compose UI Test هو النهج المفضل والأسرع.
الخلاصة
سنقوم بتطوير تطبيق جوال جاهز
تقدم IT Sectr تطبيقات iOS وAndroid للشركات الناشئة والشركات منذ عام 2017. سوف نقدم لك النصح ونقترح أفضل حل.
اقرأ أيضًا