Recomposition Jetpack Compose کا ایک طریقہ کار ہے جو ڈیٹا تبدیل ہونے پر صارف انٹرفیس کے حصوں کو خود بخود دوبارہ تعمیر کرتا ہے، بغیر دستی View اپ ڈیٹ کے۔ جب کوئی حالت متغیر جس پر Composable فنکشن منحصر ہے اپنی قدر تبدیل کرتا ہے، Compose صرف اس فنکشن کو دوبارہ شروع کرتا ہے، باقی UI درخت کو اچھوتا چھوڑتا ہے۔ Google Android Developers, 2026 کے مطابق، Recomposition کی صحیح سمجھ غیر ضروری دوبارہ ڈرائنگ کو 40–60% تک کم کرنے کی اجازت دیتی ہے۔
اہم نکات
Recomposition Composable فنکشنز کا دوبارہ نفاذ ہے جو پہلے Composition میں حصہ لے چکے ہیں، نئے پیرامیٹر یا حالت کی اقدار کے ساتھ۔ دوبارہ ترکیب کا بنیادی مقصد پورے انٹرفیس کو شروع سے دوبارہ تعمیر کیے بغیر UI درخت کو موجودہ ڈیٹا کے ساتھ ہم آہنگ کرنا ہے۔ Composition کے برعکس، جو ایک بار ہوتا ہے، Recomposition اسکرین کی زندگی میں سینکڑوں بار متحرک ہو سکتا ہے۔
Recomposition سمارٹ باطل کاری کے اصول پر کام کرتا ہے: Compose ٹریک کرتا ہے کہ ہر Composable فنکشن کون سی State اشیاء پڑھتا ہے اور صرف انہیں دوبارہ شروع کرنے کے لیے نشان زد کرتا ہے جن کے انحصار تبدیل ہوئے ہیں۔ یہ ایک سنیپ شاٹ سسٹم کے ذریعے حاصل کیا جاتا ہے، جو عملدرآمد کے دوران تمام State پڑھنے کی کارروائیوں کو ریکارڈ کرتا ہے، اور ایک Composer جو ان انحصاروں کو مخصوص فنکشنز سے نقشہ بناتا ہے۔
یہ سمجھنا ضروری ہے: دوبارہ ترکیب کا مطلب فوری اسکرین دوبارہ ڈرائنگ نہیں ہے۔ Compose تین مراحل میں کام کرتا ہے: Composition (UI تفصیل کی تعمیر)، Layout (سائز اور مقامات کا حساب)، اور Drawing (کینوس پر رینڈرنگ)۔ اگر دوبارہ ترکیب کے بعد عناصر کے سائز اور مقامات تبدیل نہیں ہوئے ہیں، Layout مرحلہ چھوڑا جا سکتا ہے۔ اگر بصری ظاہری شکل تبدیل نہیں ہوئی — Drawing چھوڑ دیا جاتا ہے۔ یہ تین مرحلہ فن تعمیر ہر UI اپ ڈیٹ کی کم سے کم لاگت کو یقینی بناتا ہے۔
دوبارہ ترکیب کے تین اہم محرکات ہیں۔ پہلا — Composable فنکشن کے جسم میں پڑھی گئی State شے میں تبدیلی۔ جب mutableStateOf یا derivedStateOf اپنی قدر تبدیل کرتا ہے، پچھلی ترکیب میں اس State کو پڑھنے والے تمام فنکشنز دوبارہ شروع کرنے کے لیے نشان زد ہو جاتے ہیں۔
دوسرا محرک — والدین فنکشن سے کال کرنے پر Composable فنکشن کے پیرامیٹر کی تبدیلی۔ اگر والدین فنکشن ایک نئی قدر منتقل کرتا ہے (مثال کے طور پر، متن یا عدد تبدیل ہوا)، بچہ فنکشن دوبارہ شروع ہو جائے گا، چاہے وہ اندرونی طور پر State نہ پڑھے۔ Compose equals کے ذریعے نئی اور پرانی پیرامیٹر اقدار کا موازنہ کرتا ہے، اور اگر وہ برابر ہیں — فنکشن چھوڑا جا سکتا ہے۔
تیسرا محرک — CompositionLocalProvider کے ذریعے CompositionLocal تبدیلی ہے۔ .current کے ذریعے CompositionLocal پڑھنے والے تمام فنکشنز فراہم کنندہ تبدیل ہونے پر دوبارہ شروع ہو جاتے ہیں۔ یہ طریقہ کار MaterialTheme استعمال کرتا ہے: تھیم تبدیل کرنا (روشن/اندھیرا) MaterialTheme.colorScheme پڑھنے والے تمام اجزاء کی دوبارہ ترکیب کا سبب بنتا ہے۔
@Composable
fun RecompositionDemo() {
var counter by remember { mutableStateOf(0) }
var text by remember { mutableStateOf("Hello") }
Column {
Text("Counter: $counter") // recomposition when counter changes
Text("Message: $text") // recomposition when text changes
Button(onClick = { counter++ }) {
Text("+1")
}
Button(onClick = { text = "World" }) {
Text("Change Text")
}
}
}
+1 بٹن پر کلک کرنے سے counter تبدیل ہوتا ہے، جس سے صرف پہلی Text لائن اور خود Column کی دوبارہ ترکیب ہوتی ہے۔ text دکھانے والی دوسری Text لائن دوبارہ شروع نہیں ہوتی۔ یہ علیحدگی سنیپ شاٹ سسٹم کا نتیجہ ہے: ہر Composable فنکشن صرف ان State اشیاء کے بارے میں جانتا ہے جو اس نے پڑھی ہیں۔
دوبارہ ترکیب کی اصلاح صحیح ڈیٹا ڈھانچے کے انتخاب سے شروع ہوتی ہے۔ قابل تبدیلی (mutableListOf) کے بجائے ناقابل تبدیلی مجموعے (listOf، mapOf) استعمال کریں۔ Compose equals کے ذریعے پیرامیٹرز کا موازنہ کرتا ہے، اور اگر کوئی مجموعہ تبدیل ہوا لیکن equals نے true واپس کیا — فنکشن دوبارہ شروع نہیں ہوگا۔ قابل تبدیلی مجموعوں کے لیے، SnapshotStateList استعمال کریں، جو عنصر کی سطح پر درست تبدیلی کی ٹریکنگ کو نافذ کرتا ہے۔
دوسری تکنیک — UI کے مستحکم حصوں کو علیحدہ Composable فنکشنز میں نکالنا ہے۔ اگر اسکرین کا کوئی حصہ بار بار تبدیل ہونے والی حالت پر منحصر نہیں ہے، تو اسے پیرامیٹرز کے ساتھ ایک علیحدہ فنکشن میں نکالیں۔ جب دوبارہ ترکیب ہوتی ہے، مستحکم فنکشن کو وہی پیرامیٹرز ملتے ہیں، Compose ان کا موازنہ کرتا ہے اور عملدرآمد چھوڑ دیتا ہے۔ یہ اس حصے کو ایک بڑے فنکشن کے حصے کے طور پر دوبارہ شروع کرنے سے زیادہ موثر ہے جہاں کچھ پیرامیٹرز تبدیل ہوئے ہیں۔
تیسری تکنیک — LazyColumn میں کنجیاں ہیں۔ LazyColumn، LazyGrid اور دیگر سست کنٹینرز میں آئٹمز کے لیے ہمیشہ کلید بتائیں۔ کلید Compose کو فہرست تبدیل ہونے پر عناصر کی شناخت کرنے دیتی ہے: شامل کرنا، ہٹانا یا دوبارہ ترتیب دینا۔ کلید کے بغیر، Compose کسی بھی تبدیلی پر فہرست کے تمام عناصر کو دوبارہ شروع کرتا ہے، جو بڑی فہرستوں پر نمایاں کارکردگی گراوٹ کا سبب بنتا ہے۔
// Optimized structure: stable parts extracted separately
@Composable
fun OptimizedScreen(items: List<Item>) {
Column {
Header() // does not depend on items — no recomposition
Spacer(modifier = Modifier.height(8.dp))
LazyColumn {
items(items, key = { it.id }) { item ->
ItemRow(item = item) // recomposition only for changed items
}
}
}
}
@Composable
fun Header() {
Text("Item list", style = MaterialTheme.typography.headlineMedium)
}
@Composable
fun ItemRow(item: Item) {
Text(item.title)
}
Skipping ایک طریقہ کار ہے جس میں Compose Composable فنکشن کے عملدرآمد کو چھوڑ دیتا ہے اگر اس کے تمام پیرامیٹرز تبدیل نہیں ہوئے ہیں۔ Skipping کو صحیح طریقے سے کام کرنے کے لیے، پیرامیٹر کی اقسام مستحکم (stable) ہونی چاہئیں۔ Kotlin کمپائلر مندرجہ ذیل کو مستحکم کے طور پر نشان زد کرتا ہے: ابتدائی اقسام (Int، Float، Boolean)، String، lambda فنکشنز، اور وہ کلاسیں جن کے تمام فیلڈز مستحکم اور val ہیں۔
Stability @Stable یا @Immutable انوٹیشن ہے جسے اپنی مرضی کے ڈیٹا کلاسز میں شامل کیا جا سکتا ہے۔ اگر کسی کلاس میں قابل تبدیلی فیلڈ (var) ہے، تو کمپائلر اسے غیر مستحکم سمجھتا ہے، اور Compose ایسے پیرامیٹرز والے فنکشنز کو نہیں چھوڑ سکے گا۔ var والی کلاسز کے لیے، @Stable استعمال کریں اگر آپ ضمانت دیتے ہیں کہ تبدیلی کی اطلاع سنیپ شاٹ سسٹم کے ذریعے بھیجی جائے گی۔
آپ کمپائلر فلیگ -P "plugin:androidx.compose.compiler.plugins.kotlin:reportsDestination=. /reports" کے ذریعے استحکام چیک کر سکتے ہیں۔ یہ تمام Composable فنکشنز اور ان کے پیرامیٹرز کی فہرست استحکام کے ساتھ تیار کرتا ہے۔ اگر کوئی پیرامیٹر غیر مستحکم ہے — اس فنکشن کے لیے skipping ناممکن ہے، اور یہ ہر والدین کی دوبارہ ترکیب پر دوبارہ شروع ہوگا۔
| قسم | استحکام | Skipping |
|---|---|---|
| Int, Float, Boolean | مستحکم | ہاں |
| String | مستحکم | ہاں |
| Lambda | مستحکم | ہاں |
| val فیلڈ والی data class | مستحکم | ہاں |
| var فیلڈ والی data class | غیر مستحکم | نہیں |
| List<String> | غیر مستحکم | نہیں |
نوٹ: List<String> کو غیر مستحکم سمجھا جاتا ہے کیونکہ یہ ایک انٹرفیس ہے، ٹھوس نفاذ نہیں۔ Kotlin Collections Immutable لائبریری سے immutableListOf() استعمال کریں یا فہرست کو @Stable کلاس میں لپیٹیں۔ Lambda ہمیشہ مستحکم ہوتا ہے کیونکہ اس کا equals صرف حوالہ جات کا موازنہ کرتا ہے، اور کال سائٹ پر نیا lambda بننے پر والدین فنکشن بھی دوبارہ شروع ہوتا ہے۔
دوبارہ ترکیب کی نگرانی کے لیے، Android Studio Compose Recomposition Counts موڈ کے ساتھ Layout Inspector فراہم کرتا ہے۔ اس موڈ میں، ہر Composable فنکشن دوبارہ ترکیب کی تعداد اور دوبارہ شروع ہونے کی وجوہات ظاہر کرتا ہے۔ یہ آپ کو ان فنکشنز کو جلدی تلاش کرنے دیتا ہے جو بہت بار دوبارہ ترکیب ہوتے ہیں اور بنیادی وجہ کا تعین کرتے ہیں — غیر مستحکم پیرامیٹرز یا غیر ضروری State انحصار۔
اضافی ٹولز: Compose Metrics(آلاتی ٹیسٹوں کے ذریعے شماریات جمع کرنا) اور Recomposition Timer (ہر فنکشن کے عملدرآمد کے وقت کی پیمائش)۔ Google پروفائلنگ مرحلے کے دوران ان ٹولز کو فعال کرنے اور ریلیز بلڈز میں غیر فعال کرنے کی سفارش کرتا ہے، کیونکہ یہ ہر دوبارہ ترکیب پر 20% تک اوور ہیڈ شامل کرتے ہیں۔
دوبارہ ترکیب کا تجزیہ کرتے وقت، غیر ضروری دوبارہ ترکیب کے نمونے تلاش کریں: ایک فنکشن دوبارہ شروع ہوتا ہے حالانکہ اس کا آؤٹ پٹ UI تبدیل نہیں ہونا چاہیے۔ ایک عام وجہ remember کے بغیر lambda کا استعمال ہے، جہاں ہر بار ایک نیا lambda آبجیکٹ بنتا ہے اور Compose پیرامیٹر کو تبدیل شدہ سمجھتا ہے۔ حل: فکسڈ کیپچرز کے ساتھ remember { } میں lambda لپیٹیں۔
// Bad: new lambda on every parent recomposition
@Composable
fun Parent() {
Child(onClick = { doSomething() }) // new lambda every time
}
// Good: remember stabilizes the lambda
@Composable
fun Parent() {
val onClick = remember { { doSomething() } }
Child(onClick = onClick) // same reference
}
اکثر پوچھے گئے سوالات
نہیں، دوبارہ ترکیب صرف Composition مرحلہ ہے۔ اس کے بعد Layout اور Drawing عمل میں آتے ہیں۔ اگر دوبارہ ترکیب کے بعد عناصر کے سائز اور مقامات تبدیل نہیں ہوئے ہیں، Layout اور Drawing مکمل طور پر چھوڑے جا سکتے ہیں، GPU وسائل بچاتے ہوئے۔
حرکت پذیری کے دوران، دوبارہ ترکیب فی سیکنڈ 120 بار تک چل سکتی ہے (120fps)۔ عام تعامل کے لیے — فی سیکنڈ 10–60 بار۔ یہ ضروری ہے کہ ہر دوبارہ ترکیب فریم بجٹ (8–16 ms) میں فٹ ہو، ورنہ ایپلی کیشن سست ہو جائے گی۔
وجہ والدین فنکشن سے پیرامیٹر کی تبدیلی ہے۔ والدین اپنی وجہ سے دوبارہ شروع ہوتا ہے اور ایک نئی قیمت منتقل کرتا ہے۔ اس سے بچنے کے لیے، پیرامیٹر استحکام چیک کریں اور lambdas اور حساب شدہ اقدار کو مستحکم کرنے کے لیے remember استعمال کریں۔
براہ راست غیر فعال کرنا ممکن نہیں ہے، لیکن readInComposition کے ذریعے مجبوری skipping موجود ہے — State فنکشن باڈی کے باہر پڑھی جاتی ہے، جو انحصار رجسٹر نہیں کرتی۔ احتیاط سے استعمال کریں: فنکشن تبدیلیوں پر رد عمل ظاہر نہیں کرے گا، جو پرانی UI کا باعث بن سکتا ہے۔
Composition زیادہ مہنگا ہے کیونکہ یہ تمام سلاٹس اور درخت کے نوڈس کو شروع سے بناتا ہے۔ Recomposition موجودہ سلاٹس کو دوبارہ استعمال کرتا ہے اور صرف ان کی اقدار کو اپ ڈیٹ کرتا ہے۔ عملی طور پر، اسکرین کے Composition میں 2–10 ms لگتے ہیں، جبکہ ایک عنصر کی دوبارہ ترکیب میں 0.1–1 ms لگتا ہے۔
خلاصہ
ہم ایک موبائل ایپلیکیشن ٹرنکی تیار کریں گے
IT Sectr 2017 سے اسٹارٹ اپس اور کاروبار کے لیے iOS اور Android ایپلیکیشنز بناتا ہے۔ ہم آپ کو مشورہ دیں گے اور بہترین حل تجویز کریں گے۔
مزید پڑھیں