Jetpack Compose — یک جعبه ابزار مدرن اعلامی برای ساخت رابطهای اندروید در Kotlin است. توسعهدهنده UI را از طریق توابع composable توصیف میکند و جعبه ابزار به طور خودکار فقط بخشهای تغییر یافته را دوباره ترسیم میکند. بر اساس Android Developers (2026)، Jetpack Compose روی Android 5.0 (API 21) و بالاتر کار میکند، از Material Design 3 پشتیبانی میکند و به لطف سیستم Recomposition خود — یک الگوریتم diff هوشمند که فقط ویجتهای تغییر یافته را بهروز میکند — به 120 FPS در دستگاههای میانرده میرسد.
نکات اصلی
Jetpack Compose — یک چارچوب اعلامی از Google برای ساخت رابطهای کاربری اندروید است که در سال 2019 معرفی شد و در سال 2021 به انتشار پایدار رسید. بر خلاف View System قدیمی (XML + Activity/Fragment)، Compose از توابع Kotlin دارای حاشیهنویس — @Composable استفاده میکند. رابط کاربری به طور کامل در Kotlin توصیف میشود: هیچ تقسیمبندی بین XML و کد وجود ندارد. این کار کلاس خطاهای مربوط به ناسازگاری id در 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+ نیاز دارد. Compose BOM (Bill of Materials) نسخههای تمام کتابخانههای Compose را همگامسازی میکند. چارچوب با کد موجود در View System سازگار است: Compose از طریق ComposeView در XML، و نمای قدیمی از طریق AndroidView در سلسلهمراتب Compose جاسازی میشود. طبق دادههای Google Play Console (2025)، Android 5.0+ 97% دستگاههای فعال را پوشش میدهد، بنابراین سازگاری برای اکثر پروژهها محدودیت محسوب نمیشود.
@Composable — حاشیهنویسی است که یک تابع معمولی Kotlin را به بلوک ساختمانی UI تبدیل میکند. تابع Composable توصیف میکند که یک قطعه از رابط کاربری — متن، دکمه، لیست — چگونه باید به نظر برسد. این تابع به جای بازگرداندن مقدار، مؤلفههای UI را به ترکیب (composition) منتشر میکند. این شبیه یک تولیدکننده است: هر تابع در هنگام فراخوانی عناصر را به صفحه اضافه میکند.
@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 منتشر میکند. ترکیب (Composition) — درختی از مؤلفههای منتشر شده در یک پاس است. اگر پارامترها تغییر نکرده باشند، Compose فراخوانی تابع را رد میکند (recomposition skip). اگر فقط name تغییر کرده باشد، فقط Text فراخوانی میشود و بقیه عناصر دوباره ترسیم نخواهند شد. چنین intelligent recomposition — مزیت اصلی عملکرد Compose در مقایسه با بهینهسازی دستی View System است.
توابع Composable به طور فعال از slot ها استفاده میکنند — trailing lambda، content: @Composable (() -> Unit). این امکان ایجاد کانتینرها را فراهم میکند: Card، Column، Row لامبدای content را دریافت میکنند و محتوا در محل slot جاسازی میشود. Slot API جایگزین ویژگیهای XML مانند android:layout_gravity شد — اکنون موقعیت عناصر فرزند در داخل بلوک content با کد Kotlin تعیین میشود.
حالت (State) در Compose — هر مقداری است که میتواند در طول زمان تغییر کند. وقتی حالت تغییر میکند، Compose recomposition را برای تمام مؤلفههایی که این حالت را میخوانند برنامهریزی میکند. مکانیزم شبیه React hooks است: mutableStateOf MutableState را برمیگرداند، خواندن .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 مقدار را بین recomposition ها حفظ میکند — در غیر این صورت mutableStateOf در هر بهروزرسانی UI دوباره ایجاد میشد. collectAsState() StateFlow را از ViewModel به حالت سازگار با Compose تبدیل میکند. توصیه — برای حالت صفحه از ViewModel با StateFlow، برای حالت محلی (مثلاً کارت باز شده) از mutableStateOf استفاده کنید. این تقسیمبندی با اصل مؤلفههای «هوشمند/ساده» مطابقت دارد.
State Hoisting — الگوی انتقال حالت از مؤلفه فرزند به والد است. والد مقدار و 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 box model است: padding → background مانند margin + background عمل میکند؛ background → padding — مانند background + padding در داخل. کافی است توسعهدهنده به خاطر بسپارد: padding اول = فاصله خارجی، padding بعد = داخلی.
اگر اصلاحکنندههای داخلی کافی نباشند، یک اصلاحکننده سفارشی از طریق Modifier.composed { ... } یا Modifier.then() ایجاد میشود. در داخل اصلاحکننده سفارشی میتوان از اندازهگیریهای layout (Modifier.layout { measurable, constraints -> ... })، رسم (Modifier.drawWithContent { ... })، حرکات (Modifier.pointerInput { ... }) استفاده کرد. مثال: اصلاحکننده برای انیمیشن ضربانی هنگام کلیک — اندازه را اندازهگیری میکند، با کلیک انیمیشن مقیاس را از طریق animateFloatAsState شروع میکند.
برای انیمیشنها Compose animate*AsState (animateFloatAsState، animateColorAsState، animateDpAsState) را ارائه میدهد — مقادیر بین حالت قدیم و جدید در زمان تغییر انیمیشن میشوند. اگر انیمیشن ظاهر/ناپدید شدن نیاز است — AnimatedVisibility و AnimatedContent با انتقالهای داخلی (fade، slide، expand). همه انیمیشنها روی graphics layer کار میکنند و باعث ترکیب اضافی نمیشوند.
توابع Composable نباید اقدامات جانبی را مستقیماً انجام دهند (درخواستهای شبکه، تایمرها، اشتراکها) — آنها در هر recomposition فراخوانی میشوند که منجر به تکرار درخواستها میشود. برای اثرات جانبی Compose خانواده توابع Effect را ارائه میدهد: LaunchedEffect هنگام ورود به ترکیب یک کوروتین راهاندازی میکند و هنگام خروج لغو میکند، 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 تغییر کند دوباره راهاندازی میشود — کوروتین قبلی لغو میشود و کوروتین جدید با userId جدید شروع میشود. این کار مدیریت دستی لغو درخواستها را حذف میکند. DisposableEffect(Unit) — اثری با کلید ثابت Unit، هنگام ورود به ترکیب فعال میشود و هنگام خروج onDispose را فراخوانی میکند. SensorReader شنونده را ثبت میکند و هنگام خروج از صفحه لغو اشتراک میکند — بدون خطر نشت حافظه.
اگر کوروتین باید نه هنگام ورود به ترکیب، بلکه با یک رویداد (فشردن دکمه) راهاندازی شود، از rememberCoroutineScope() استفاده میشود. این تابع CoroutineScope متصل به چرخه حیات Composable را برمیگرداند و به DisposableEffect نیاز ندارد. مثال: راهاندازی درخواست شبکه با کلیک روی دکمه — scope.launch { viewModel.loadData() }.
انتخاب بین Compose و View System — سؤال اصلی معماری توسعهدهنده اندروید در سال 2026 است. هر دو فناوری توسط Google پشتیبانی میشوند، اما Compose جهت اصلی است که Google منابع خود را روی آن متمرکز میکند. View System فقط اصلاحات بحرانی دریافت میکند و توسعه نمییابد. تفاوت در نحو، مدیریت حالت، عملکرد و زمان توسعه آشکار میشود.
| جنبه | Jetpack Compose | View System |
|---|---|---|
| توصیف UI | توابع Kotlin @Composable | XML + Activity/Fragment |
| حالت | mutableStateOf، StateFlow، ترسیم مجدد خودکار | findViewById، دستی: setText، notifyDataSetChanged |
| عملکرد | Intelligent recomposition، رندر Canvas | سلسلهمراتب View، measure/layout/draw |
| انیمیشنها | animate*AsState، AnimatedVisibility، داخلی | ValueAnimator، ObjectAnimator، Transition |
| سازگاری | minSdk 21، پلهای ComposeView/AndroidView | همه نسخهها |
| اندازه APK | 3-5+ مگابایت برای Compose | بدون سربار اضافی |
برای پروژههای جدید Google Jetpack Compose را به عنوان استاندارد توسعه UI توصیه میکند. View System برای پشتیبانی از کد نوشته شده قبل از 2021 و مواردی که اندازه حداقلی APK مورد نیاز است (مثلاً برای بازارهای در حال توسعه با دستگاههای سطح ابتدایی) باقی میماند. Compose حجم کد UI را 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 از سال 2017 برنامههای iOS و Android را برای استارتاپها و کسبوکارها ایجاد میکند. ما به شما مشاوره میدهیم و بهترین راهحل را پیشنهاد خواهیم کرد.