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 अपना मान बदलता है, पिछली composition में इस 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 और अन्य आलसी कंटेनरों में item के लिए हमेशा key निर्दिष्ट करें। कुंजी 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, लैम्ब्डा फ़ंक्शन, और वे वर्ग जिनके सभी फ़ील्ड स्थिर और val हैं।
Stability @Stable या @Immutable एनोटेशन है जिसे कस्टम डेटा क्लास में जोड़ा जा सकता है। यदि क्लास में परिवर्तनीय फ़ील्ड (var) है, तो कंपाइलर इसे अस्थिर मानता है, और Compose ऐसे पैरामीटर वाले फ़ंक्शन को छोड़ नहीं पाएगा। var वाले क्लास के लिए, @Stable का उपयोग करें यदि आप गारंटी देते हैं कि परिवर्तन सूचना स्नैपशॉट सिस्टम के माध्यम से भेजी जाएगी।
आप कंपाइलर फ़्लैग -P "plugin:androidx.compose.compiler.plugins.kotlin:reportsDestination=. /reports" के माध्यम से stability जाँच सकते हैं। यह सभी Composable फ़ंक्शन और उनके पैरामीटर की सूची के साथ stability दर्शाने वाली एक रिपोर्ट उत्पन्न करता है। यदि पैरामीटर अस्थिर है — उस फ़ंक्शन के लिए skipping असंभव है, और यह प्रत्येक मूल पुनर्संरचना पर पुनर्स्टार्ट होगा।
| प्रकार | स्थिरता | Skipping |
|---|---|---|
| Int, Float, Boolean | स्थिर | हाँ |
| String | स्थिर | हाँ |
| लैम्ब्डा | स्थिर | हाँ |
| val फ़ील्ड वाली data class | स्थिर | हाँ |
| var फ़ील्ड वाली data class | अस्थिर | नहीं |
| List<String> | अस्थिर | नहीं |
नोट: List<String> को अस्थिर माना जाता है क्योंकि यह एक इंटरफ़ेस है, ठोस कार्यान्वयन नहीं। Kotlin Collections Immutable लाइब्रेरी से immutableListOf() का उपयोग करें या सूची को @Stable क्लास में लपेटें। लैम्ब्डा हमेशा स्थिर होता है क्योंकि इसका equals केवल संदर्भों की तुलना करता है, और कॉल साइट पर नया लैम्ब्डा बनाने पर मूल फ़ंक्शन भी पुनर्स्टार्ट होता है।
पुनर्संरचना की निगरानी के लिए, Android Studio Compose Recomposition Counts मोड के साथ Layout Inspector प्रदान करता है। इस मोड में, प्रत्येक Composable फ़ंक्शन पुनर्संरचना की संख्या और पुनर्स्टार्ट के कारणों को प्रदर्शित करता है। यह आपको उन फ़ंक्शन को जल्दी से खोजने की अनुमति देता है जो बहुत बार पुनर्संरचित होते हैं और मूल कारण निर्धारित करते हैं — अस्थिर पैरामीटर या अनावश्यक State निर्भरताएँ।
अतिरिक्त उपकरण: Compose Metrics (इंस्ट्रुमेंटेशन परीक्षणों के माध्यम से सांख्यिकी संग्रह) और Recomposition Timer (प्रत्येक फ़ंक्शन के निष्पादन समय का मापन)। Google प्रोफाइलिंग चरण के दौरान इन उपकरणों को सक्षम करने और रिलीज़ बिल्ड में अक्षम करने की अनुशंसा करता है, क्योंकि ये प्रति पुनर्संरचना 20% तक ओवरहेड जोड़ते हैं।
पुनर्संरचना का विश्लेषण करते समय, अनावश्यक पुनर्संरचना पैटर्न देखें: एक फ़ंक्शन पुनर्स्टार्ट होता है भले ही उसका आउटपुट UI नहीं बदलना चाहिए। एक सामान्य कारण बिना remember के लैम्ब्डा का उपयोग है, जहाँ हर बार एक नया लैम्ब्डा ऑब्जेक्ट बनता है और Compose पैरामीटर को बदला हुआ मानता है। समाधान: निश्चित कैप्चर के साथ remember { } में लैम्ब्डा लपेटें।
// 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) में फिट हो, अन्यथा एप्लिकेशन लैग करेगा।
कारण मूल फ़ंक्शन से पैरामीटर में बदलाव है। मूल अपने कारण से पुनर्स्टार्ट होता है और एक नया मान पास करता है। इससे बचने के लिए, पैरामीटर stability की जाँच करें और लैम्ब्डा और गणना मानों को स्थिर करने के लिए remember का उपयोग करें।
सीधा अक्षमीकरण नहीं है, लेकिन readInComposition के माध्यम से forced skipping है — State फ़ंक्शन बॉडी के बाहर पढ़ा जाता है, जो निर्भरता पंजीकृत नहीं करता। इसे सावधानी से उपयोग करें: फ़ंक्शन परिवर्तनों पर प्रतिक्रिया नहीं करेगा, जो पुराने UI का कारण बन सकता है।
Composition अधिक महंगा है क्योंकि यह सभी स्लॉट और ट्री नोड को शुरू से बनाता है। Recomposition मौजूदा स्लॉट का पुन: उपयोग करता है और केवल उनके मानों को अपडेट करता है। व्यवहार में, स्क्रीन के Composition में 2–10 ms लगते हैं, जबकि एकल तत्व की पुनर्संरचना में 0.1–1 ms लगता है।
सारांश
हम एक मोबाइल एप्लिकेशन टर्नकी विकसित करेंगे
IT Sectr 2017 से स्टार्टअप और व्यवसायों के लिए iOS और Android एप्लिकेशन बनाता है। हम आपको सलाह देंगे और सर्वोत्तम समाधान प्रस्तावित करेंगे।
यह भी पढ़ें