Jetpack Compose — فریمورک مدرن UI اعلامی از گوگل برای توسعه اندروید، که در نسخه پایدار 1.0 در جولای 2021 منتشر شد. Compose نشانهگذاری امری XML و سیستم View را با توابع کاتلین با حاشیهنویسی @Composable جایگزین میکند. طبق Google I/O (2025)، Compose در 55% پروژههای جدید اندروید استفاده میشود و اندازه متوسط کد UI نسبت به XML 30–50% کاهش مییابد. فریمورک با تغییر State فقط بخشهای تغییر یافته صفحه را بهطور خودکار بازترسیم میکند و فراخوانی دستی notifyDataSetChanged یا findViewById را حذف میکند.
نکات اصلی
Jetpack Compose — فریمورک UI گوگل ساخته شده بر اساس اصول برنامهنویسی واکنشگرا. به جای Activity با طرحبندی XML، FragmentManager و ViewBinding، توسعهدهنده رابط را از طریق توابع کاتلین با حاشیهنویسی @Composable توصیف میکند. Compose از LayoutInflater استفاده نمیکند — UI توابع خالص کاتلین هستند که به بایتکد کامپایل میشوند. فریمورک از چند کتابخانه تشکیل شده است: Compose UI (اجزای پایه Text, Button, Column, Row)، Compose Foundation (Material Design، حرکات، Focus)، Compose Material3 (Material You با Dynamic Colors) و Compose Runtime (State، Side Effects، Coroutines). Compose روی Android API 21+ (اندروید 5.0) کار میکند و از طریق ComposeView — آداپتر AndroidView با کدهای View/XML موجود کاملاً سازگار است.
View System (2008) از سلسلهمراتب اشیاء View با مدیریت دستی استفاده میکند: توسعهدهنده طرح XML ایجاد میکند، View را از طریق findViewById پیدا میکند، Adapter را برای RecyclerView پیادهسازی میکند و هنگام تغییر داده notifyDataSetChanged را فراخوانی میکند. Compose UI را تابعی توصیف میکند: هنگام تغییر وضعیت، فریمورک فقط توابع Composable تغییر یافته را مجدداً راهاندازی (recompose) میکند، diff را محاسبه و حداقل تغییرات را در Canvas اعمال میکند. عملکرد Compose قابل مقایسه با View System است و در سناریوهای با لیستهای پیچیده (LazyColumn) اغلب به دلیل رد شدن از عناصر غیرضروری از طریق پارامتر key از RecyclerView بهتر عمل میکند. در IT Sectr از Compose برای ماژولهای جدید برنامههای اندروید با minSdk 24+ استفاده میشود.
@Composable — حاشیهنویسی که یک تابع معمولی کاتلین را به بلوک سازنده UI تبدیل میکند. توابع 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> با پشتیبانی از سیستم اسنپشات Compose ایجاد میکند. اسنپشات — مکانیزم ردیابی تغییرات: هنگام نوشتن در State، Compose اسنپشات فعلی را به عنوان 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 delegate امکان استفاده از State به عنوان متغیر معمولی را فراهم میکند: liked = !liked به جای liked.value = !liked.value. رنگ دکمه به طور واکنشی بین primary (پسندیده) و surfaceVariant (پسندیده نشده) تغییر میکند.
remember — تابع Compose که مقدار را بین بازآفرینیها ذخیره میکند. بدون remember هر راهاندازی مجدد تابع Composable وضعیت جدید (mutableStateOf) ایجاد میکند — این منطق برنامه را خراب میکند: با چرخش صفحه یا تغییر State والد، شمارنده بازنشانی میشود. remember یک لامبدا-محاسبهگر میپذیرد و مقدار را فقط در اولین ترکیب محاسبه میکند؛ در موارد بعدی نتیجه ذخیره شده را برمیگرداند. برای بازنشانی حافظه از 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 = "مدت زمان سپری شده: ${seconds}s",
style = MaterialTheme.typography.displayMedium
)
}
}rememberSaveable seconds را هنگام چرخش صفحه (تغییر پیکربندی) حفظ میکند. LaunchedEffect یک کوروتین راهاندازی میکند که هر ثانیه 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("کارت کلیک شد") },
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 اعلامی برای اندروید با State و Modifier",
style = MaterialTheme.typography.bodyMedium
)
}
}
}CardExample زنجیره Modifier را نشان میدهد: fillMaxWidth + padding + clickable. Card — مؤلفه Material3 با تنظیمات خاص elevation و colors. Column تو در تو دارای padding داخلی 16dp است. Compose Material3 بهطور خودکار رنگها را با Dynamic Color (Material You) در اندروید 12+ تطبیق میدهد. Card یکی از 30+ مؤلفه داخلی Material3 در Compose است.
State hoisting — الگوی بالابردن وضعیت از تابع Composable به فراخواننده آن، که تابع را stateless میکند. مؤلفه stateless دادهها و callbackها را از طریق پارامترها دریافت میکند و صاحب State خود نیست. این قابلیت استفاده مجدد و آزمایشپذیری را افزایش میدهد: مؤلفه را میتوان با Stateهای مختلف فراخوانی و در preview آزمایش کرد. گوگل معماری زیر را توصیه میکند: ViewModel + StateFlow (یا MutableStateFlow) + collectAsState() در Compose. ViewModel وضعیت را به سطح صفحه بالامیبرد، Compose نمایش میدهد. عوارض جانبی (LaunchedEffect, DisposableEffect) رویدادهای یکبار مصرف را پردازش میکنند.
| مؤلفه | مسئولیت | فناوری |
|---|---|---|
| ViewModel | ذخیره State، منطق کسبوکار | StateFlow, MutableStateFlow |
| Screen Composable | سازماندهی صفحه، State hoisting | collectAsState(), Scaffold, LazyColumn |
| Stateless Component | UI بدون وضعیت، نمایش خالص | @Composable پارامترها + لامبداها |
| Side Effect | اقدامات یکبار مصرف (snackbar، ناوبری) | LaunchedEffect, SnackbarHostState |
سوالات متداول
طرحبندی XML امری است: LayoutInflater XML را بارگذاری میکند، findViewById View را پیدا میکند، توسعهدهنده به صورت دستی متن/لیستها را بهروز میکند. Compose اعلامی است: UI با توابع کاتلین @Composable توصیف میشود و فریمورک با تغییر State فقط بخشهای تغییر یافته را بهطور خودکار بازترسیم میکند. Compose حجم کد UI را 30–50% کاهش میدهد و از XML استفاده نمیکند.
بله، گوگل Navigation Compose را ارائه میدهد — کتابخانهای برای ناوبری اعلامی بین صفحات. NavController پشته مسیرها را مدیریت میکند، composable() صفحات را ثبت میکند، navArgument پارامترها را منتقل میکند. جایگزینها: Voyager (اجتماعی) و 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+ (اندروید 5.0 Lollipop) از طریق Compose Compiler و Compose BOM پشتیبانی میکند. Material 3 (Dynamic Colors) در اندروید 12+ در دسترس است؛ در نسخههای قدیمیتر از پالت fallback استفاده میشود. برای پروژههای جدید اپل minSdk 24+ (اندروید 7.0) را توصیه میکند که کاملاً توسط Compose پوشش داده میشود.
گوگل Compose UI Test را ارائه میدهد — کتابخانهای برای تست روی JVM (دسکتاپ) و شبیهساز. توابع اصلی: composeTestRule.setContent { } برای رندر مؤلفه، onNodeWithText() برای جستجوی عناصر، performClick()/performTextInput() برای اقدامات. تستهای Espresso از طریق ComposeTestRule با Compose سازگار هستند، اما Compose UI Test رویکرد ترجیحی و سریعتری است.
خلاصه
ما یک اپلیکیشن موبایل به صورت کلید در دست توسعه خواهیم داد
IT Sectr از سال 2017 برنامههای iOS و Android را برای استارتاپها و کسبوکارها ایجاد میکند. ما به شما مشاوره میدهیم و بهترین راهحل را پیشنهاد خواهیم کرد.
همچنین بخوانید