Composable Function — واحد بنیادین رابط کاربری در Jetpack Compose است که مشخص میکند یک بخش از صفحه چگونه باید به نظر برسد و رفتار کند. هر یک از این توابع با annotation @Composable مشخص شده و در زمینه خاصی اجرا میشود که به Compose امکان میدهد وابستگیها را ردیابی کرده و UI را به طور خودکار هنگام تغییر دادهها بازسازی کند. به گفته Google Android Developers, 2026, ساخت صحیح توابع Composable به طور مستقیم بر عملکرد برنامه و کارایی بازآرایی تأثیر میگذارد.
نکات اصلی
Composable Function — تابعی در زبان Kotlin است که با annotation @Composable مشخص شده و بخشی از رابط کاربری را به صورت اعلامی توصیف میکند. به جای ایجاد و پیکربندی اشیاء View از طریق کد Java یا نشانهگذاری XML، توسعهدهنده به سادگی مینویسد که UI در هر وضعیت دادهای چگونه باید به نظر برسد.
تفاوت اصلی بین تابع Composable و سیستم View سنتی Android در مدل بهروزرسانی است. در رویکرد کلاسیک، توسعهدهنده دستی findViewById را فراخوانی میکرد، متن را از طریق setText تغییر میداد، visibility را از طریق setVisibility مدیریت میکرد. Composable Function از این روال آزاد میکند: هنگام تغییر دادهها، سیستم خود تعیین میکند کدام توابع باید دوباره اجرا شوند و فقط آنها را اجرا میکند.
کامپایلر Kotlin با پردازش annotation @Composable کد اضافی تولید میکند که تابع را در مکانیسم ترکیب یکپارچه میکند. این کد شامل خواندن و نوشتن در slotها — سلولهای حافظه ویژهای که وضعیت و پارامترهای هر تابع Composable را در درخت UI فعلی ذخیره میکند — است. به لطف این یکپارچهسازی، Compose میداند کدام توابع به کدام دادهها وابسته هستند.
نحو تابع Composable بسیار فشرده است: کافی است @Composable را قبل از کلمه کلیدی fun اضافه کنید. تابع میتواند هر پارامتری را بپذیرد، شامل فراخوانیهای Composable دیگر در بدنه خود باشد و از ساختارهای Kotlin — شرطها، حلقهها، عبارات when — برای نمایش شرطی UI استفاده کند.
@Composable
fun ProductItem(
product: Product,
modifier: Modifier = Modifier,
onAddToCart: () -> Unit
) {
Card(modifier = modifier.padding(8.dp)) {
Row(modifier = Modifier.fillMaxWidth().padding(12.dp),
verticalAlignment = Alignment.CenterVertically) {
Column(modifier = Modifier.weight(1f)) {
Text(text = product.name, style = MaterialTheme.typography.titleMedium)
Text(text = "${product.price}", color = MaterialTheme.colorScheme.primary)
}
Button(onClick = onAddToCart) {
Text("افزودن به سبد خرید")
}
}
}
}
در این مثال، تابع Composable ProductItem یک شی Product، یک اصلاحکننده و یک callback را میپذیرد. هر سه پارامتر تغییرناپذیر هستند که رفتار قابل پیشبینی را در بازآرایی تضمین میکند. اصلاحکننده به عنوان پارامتر با مقدار پیشفرض منتقل شده است — این یک رویه استاندارد است که به طرف فراخواننده اجازه میدهد فاصلهها و اندازهها را سفارشی کند.
در داخل تابع Composable از کامپوننتهای داخلی Material Design (Text, Button, Card, TextField) یا اولیههای بنیادین (Canvas, Layout) استفاده میشود. هر کامپوننت پارامترهایی برای پیکربندی ظاهر و رفتار و همچنین یک یا چند اصلاحکننده از طریق پارامتر modifier دریافت میکند.
اصلاحکنندهها (Modifier) — زنجیرهای از توابع هستند که اندازه، موقعیت، مدیریت رویداد و ظاهر کامپوننت را تغییر میدهند. ترتیب اصلاحکنندهها در زنجیره مهم است: clickable.semantics با semantics.clickable متفاوت کار میکند و padding.background پس زمینه ناحیه را همراه با padding رنگ میکند که در طراحی بسیار مهم است.
در داخل تابع Composable میتوان از شرطهای if و when برای نمایش شرطی بخشهایی از UI و از حلقههای for برای لیستهای پویا استفاده کرد. همه این ساختارها به طور طبیعی کار میکنند زیرا Kotlin یک زبان برنامهنویسی کامل است. با این حال مهم است به خاطر داشته باشید: اگر شرط یا حلقه شامل فراخوانی توابع Composable باشد، آنها نیز در بازآرایی شرکت میکنند.
@Composable
fun ProductList(
products: List<Product>,
modifier: Modifier = Modifier
) {
LazyColumn(modifier = modifier) {
items(products, key = { it.id }) { product ->
ProductItem(
product = product,
onAddToCart = { /* add to cart */ }
)
}
}
}
بیایید نمونه صفحه جستجوی محصولات را با استفاده از چند تابع Composable بررسی کنیم. در اینجا الگوهای معمولی نشان داده شده است: فیلد ورودی با وضعیت، فیلتر کردن لیست، مدیریت نتیجه خالی و بارگذاری.
data class Product(
val id: String,
val name: String,
val price: Double,
val category: String
)
@Composable
fun SearchScreen() {
var query by remember { mutableStateOf("") }
val products = remember(query) { getFilteredProducts(query) }
Column(modifier = Modifier.fillMaxSize().padding(16.dp)) {
OutlinedTextField(
value = query,
onValueChange = { query = it },
label = { Text("جستجوی محصولات") },
modifier = Modifier.fillMaxWidth()
)
Spacer(modifier = Modifier.height(16.dp))
when (products) {
is Loading -> CircularProgressIndicator()
is Empty -> Text("نتیجهای یافت نشد")
is Result -> LazyColumn {
items(products.items, key = { it.id }) { product ->
ProductItem(product = product, onAddToCart = {})
}
}
}
}
}
این مثال چندین اصطلاح را به طور همزمان نشان میدهد: remember برای ذخیره وضعیت جستجو، remember(query) برای فیلتر کردن با کلید، when برای سه وضعیت UI و LazyColumn برای نمایش کارآمد لیست. هر یک از این اصطلاحات نتیجه تجربه عملی در توسعه برنامههای Compose است.
توابع Composable پارامترها را مانند توابع معمولی Kotlin میپذیرند، اما با یک تفاوت مهم: پارامتر میتواند یک تابع Composable دیگر باشد که از طریق lambda با annotation @Composable منتقل میشود. این مکانیسم Slot API نام دارد و الگوی اصلی برای ایجاد کانتینرهای قابل استفاده مجدد است.
Slot API مشکلی را حل میکند که در سیستم View سنتی از طریق ViewGroup و افزودن برنامهای Viewهای فرزند حل میشد. به جای متدهای addView، Compose از lambdaهای content استفاده میکند — آخرین پارامتر با نوع @Composable () -> Unit. طرف فراخواننده هر UI را به این lambda منتقل میکند و خود کانتینر فقط موقعیت آن را تعیین میکند.
پارامترهای تابع Composable میتوانند مقادیر پیشفرض داشته باشند که استفاده از آنها را در زمینههای مختلف ساده میکند. توصیه میشود فقط پارامترهایی را اجباری کنید که تابع بدون آنها نمیتواند وظیفه خود را انجام دهد و بقیه را با مقادیر پیشفرض منطقی تجهیز کنید.
| پارامتر | نوع | مثال |
|---|---|---|
| اجباری | هر نوع | name: String |
| اختیاری | با مقدار پیشفرض | modifier: Modifier = Modifier |
| Content | @Composable () -> Unit | content: @Composable () -> Unit |
| Callback | lambda بدون @Composable | onClick: () -> Unit |
در جامعه Compose چندین اصطلاح تثبیت شده شکل گرفته است که توابع Composable را خواناتر و قابل پیشبینیتر میکند. اولین — State Hoisting: وضعیت به سطح بالاتری منتقل میشود و تابع Composable آن را از طریق پارامترها دریافت میکند. این تابع را خالص و در زمینههای مختلف قابل استفاده مجدد میکند.
دومین اصطلاح — پارامترهای Event-driven. به جای ارسال ViewModel یا useCase به تابع Composable، فقط callbackهای مشخصی منتقل میشود: onSave, onDelete, onNavigateToDetail. این وابستگی را کاهش میدهد و تست را ساده میکند — برای تست ProductItem به ViewModel نیاز نیست، فقط یک lambda-stub کافی است.
سومین اصطلاح — CompositionLocal برای انتقال دادههای مشترک از طریق درخت ترکیب. تم، چگالی صفحه، مسیر فعلی — همه اینها از طریق CompositionLocal منتقل میشود و از زنجیرههای پارامتر از طریق دهها تابع Composable جلوگیری میکند. با این حال نباید از CompositionLocal سوءاستفاده کرد: پارامترهای صریح همیشه بر وابستگیهای ضمنی ترجیح دارند.
// State Hoisting: وضعیت به تابع والد منتقل شد
@Composable
fun CounterDisplay(
count: Int,
onIncrement: () -> Unit
) {
Column(horizontalAlignment = Alignment.CenterHorizontally) {
Text(text = "شمارنده: $count", style = MaterialTheme.typography.headlineLarge)
Button(onClick = onIncrement) {
Text("+1")
}
}
}
// استفاده با State Hoisting
@Composable
fun CounterScreen() {
var count by remember { mutableStateOf(0) }
CounterDisplay(
count = count,
onIncrement = { count++ }
)
}
سوالات متداول
بله، return مجاز است اما با احتیاط. Compose بازآرایی را در سطح توابع جداگانه بهینه میکند و return زودهنگام ممکن است این بهینهسازی را مختل کند. بهتر است از عملگرهای شرطی if یا when در بدنه تابع استفاده کنید.
در Kotlin Unit یک شیء singleton است، نه یک نوع خالی. توابع Composable Unit را برمیگردانند که از نظر فنی به این معنی است که خود شیء Unit را برمیگردانند. با این حال در عمل این مهم نیست — مقدار بازگشتی توسط سیستم ترکیب نادیده گرفته میشود.
انتقال مجموعههای قابل تغییر ممکن است اما این رویه بدی است. اگر مجموعه تغییر کند، Compose از آن مطلع نخواهد شد زیرا مرجع به شیء یکسان باقی میماند. برای تغییرات قابل ردیابی از لیستهای immutable یا mutableStateListOf استفاده کنید.
برای دیباگ از Android Studio با Layout Inspector استفاده کنید که درخت فعلی توابع Composable، مقادیر پارامترها و دلایل بازآرایی را نشان میدهد. همچنین دیباگر معمولی Kotlin کار میکند — نقاط توقف داخل توابع Composable در هر بازآرایی به درستی فعال میشوند.
تابع Composable همیشه Unit را برمیگرداند، بنابراین return type مشخص نمیشود. تلاش برای برگرداندن نوع دیگر خطای کامپایل ایجاد میکند زیرا annotation @Composable با انواع بازگشتی غیر از Unit ناسازگار است.
خلاصه
ما یک اپلیکیشن موبایل به صورت کلید در دست توسعه خواهیم داد
IT Sectr از سال 2017 برنامههای iOS و Android را برای استارتاپها و کسبوکارها ایجاد میکند. ما به شما مشاوره میدهیم و بهترین راهحل را پیشنهاد خواهیم کرد.
همچنین بخوانید