ज़्यादातर यूज़र इंटरफ़ेस (यूआई) टूलकिट की तरह, Compose भी कई अलग-अलग फ़ेज़ के ज़रिए फ़्रेम रेंडर करता है. उदाहरण के लिए, Android View सिस्टम में तीन मुख्य चरण होते हैं: मेज़र, लेआउट, और ड्रॉइंग. 'लिखें' सुविधा भी काफ़ी हद तक इसी तरह काम करती है. हालांकि, इसमें एक ज़रूरी चरण कंपोज़िशन शामिल है, जो शुरुआत में होता है.
Compose के दस्तावेज़ में, Compose के बारे में सोचना और स्टेट और Jetpack Compose में कंपोज़िशन के बारे में बताया गया है.
फ़्रेम के तीन चरण
Compose में तीन मुख्य फ़ेज़ होते हैं:
- कंपोज़िशन: कौनसा यूज़र इंटरफ़ेस दिखाना है. Compose, कंपोज़ेबल फ़ंक्शन चलाता है और आपके यूज़र इंटरफ़ेस का ब्यौरा बनाता है.
- लेआउट: यूज़र इंटरफ़ेस (यूआई) को कहां रखना है. इस चरण में दो काम किए जाते हैं: मेज़रमेंट और प्लेसमेंट. लेआउट एलिमेंट, लेआउट ट्री में मौजूद हर नोड के लिए, खुद को और किसी भी चाइल्ड एलिमेंट को 2D कोऑर्डिनेट में मेज़र और प्लेस करते हैं.
- ड्रॉइंग: यह कैसे रेंडर होती है. यूज़र इंटरफ़ेस (यूआई) एलिमेंट, कैनवस में ड्रॉ किए जाते हैं. आम तौर पर, यह डिवाइस की स्क्रीन होती है.
आम तौर पर, इन फ़ेज़ का क्रम एक जैसा होता है. इससे डेटा, एक ही दिशा में फ़्लो होता है. जैसे, कंपोज़िशन से लेआउट, लेआउट से ड्रॉइंग, और ड्रॉइंग से फ़्रेम जनरेट होता है. इसे एकतरफ़ा डेटा फ़्लो भी कहा जाता है. BoxWithConstraints, LazyColumn, और LazyRow ऐसे कॉम्पोनेंट हैं जिनमें बच्चों की कंपोज़िशन, पैरंट के लेआउट फ़ेज़ पर निर्भर करती है.
सैद्धांतिक तौर पर, ये सभी फ़ेज़ हर फ़्रेम के लिए होते हैं. हालांकि, परफ़ॉर्मेंस को ऑप्टिमाइज़ करने के लिए, Compose ऐसे काम को दोहराने से बचता है जिससे इन सभी फ़ेज़ में एक जैसे इनपुट से एक जैसे नतीजे मिलते हैं. अगर कंपोज़ेबल फ़ंक्शन के पिछले नतीजे का फिर से इस्तेमाल किया जा सकता है, तो कंपोज़ उसे नहीं चलाता. साथ ही, अगर ज़रूरत नहीं है, तो Compose UI पूरे ट्री को फिर से लेआउट या फिर से ड्रॉ नहीं करता. Compose, यूज़र इंटरफ़ेस (यूआई) को अपडेट करने के लिए सिर्फ़ उतना काम करता है जितना ज़रूरी है. यह ऑप्टिमाइज़ेशन इसलिए किया जा सकता है, क्योंकि Compose अलग-अलग फ़ेज़ में स्टेट रीड को ट्रैक करता है.
फ़ेज़ के बारे में जानकारी
इस सेक्शन में, कंपोज़ेबल के लिए कंपोज़ के तीन चरणों को ज़्यादा जानकारी के साथ बताया गया है.
कंपोज़िशन
कंपोज़िशन फ़ेज़ में, Compose रनटाइम, कंपोज़ेबल फ़ंक्शन को लागू करता है. साथ ही, एक ट्री स्ट्रक्चर आउटपुट करता है, जो आपके यूज़र इंटरफ़ेस (यूआई) को दिखाता है. इस यूज़र इंटरफ़ेस (यूआई) ट्री में लेआउट नोड होते हैं. इनमें अगले चरणों के लिए ज़रूरी सभी जानकारी होती है. जैसा कि इस वीडियो में दिखाया गया है:
दूसरी इमेज. यह आपके यूज़र इंटरफ़ेस (यूआई) को दिखाने वाला ट्री है. इसे कंपोज़िशन फ़ेज़ में बनाया जाता है.
कोड और यूज़र इंटरफ़ेस (यूआई) ट्री का एक सबसेट इस तरह दिखता है:
इन उदाहरणों में, कोड में मौजूद हर कंपोज़ेबल फ़ंक्शन, यूज़र इंटरफ़ेस (यूआई) ट्री में मौजूद एक लेआउट नोड पर मैप करता है. ज़्यादा जटिल उदाहरणों में, कंपोज़ेबल में लॉजिक और कंट्रोल फ़्लो शामिल हो सकता है. साथ ही, अलग-अलग स्थितियों के हिसाब से अलग-अलग ट्री जनरेट किए जा सकते हैं.
लेआउट
लेआउट फ़ेज़ में, Compose, कंपोज़िशन फ़ेज़ में बनाए गए यूज़र इंटरफ़ेस (यूआई) ट्री को इनपुट के तौर पर इस्तेमाल करता है. लेआउट नोड के कलेक्शन में, हर नोड के साइज़ और 2D स्पेस में उसकी जगह तय करने के लिए ज़रूरी सभी जानकारी होती है.
चौथी इमेज. लेआउट फ़ेज़ के दौरान, यूज़र इंटरफ़ेस (यूआई) ट्री में हर लेआउट नोड की मेज़रमेंट और प्लेसमेंट.
लेआउट फ़ेज़ के दौरान, ट्री को इन तीन चरणों वाले एल्गोरिदम का इस्तेमाल करके ट्रैवर्स किया जाता है:
- बच्चों का आकलन करना: अगर कोई नोड मौजूद है, तो वह अपने बच्चों का आकलन करता है.
- अपना साइज़ तय करना: इन मेज़रमेंट के आधार पर, कोई नोड अपना साइज़ खुद तय करता है.
- बच्चों को जगह देना: हर चाइल्ड नोड को, नोड की अपनी पोज़िशन के हिसाब से रखा जाता है.
इस फ़ेज़ के आखिर में, हर लेआउट नोड में ये चीज़ें होती हैं:
- असाइन की गई चौड़ाई और ऊंचाई
- वह x, y कोऑर्डिनेट जहां इसे बनाया जाना चाहिए
पिछले सेक्शन से यूज़र इंटरफ़ेस (यूआई) ट्री को वापस लाएं:
इस ट्री के लिए, एल्गोरिदम इस तरह काम करता है:
- ,
Image, औरColumn,Rowके चाइल्ड व्यू हैं. Imageको मेज़र किया जाता है. इसमें कोई चाइल्ड नहीं होता. इसलिए, यह अपना साइज़ खुद तय करता है औरRowको साइज़ की जानकारी देता है.- इसके बाद,
Columnको मेज़र किया जाता है. यह सबसे पहले अपने चाइल्ड (दोTextकंपोज़ेबल) को मेज़र करता है. - पहले
Textको मेज़र किया जाता है. इसमें कोई चाइल्ड नोड नहीं होता. इसलिए, यह अपना साइज़ खुद तय करता है औरColumnको इसकी जानकारी देता है.- दूसरे
Textको मेज़र किया जाता है. इसमें कोई चाइल्ड एलिमेंट नहीं होता. इसलिए, यह अपने साइज़ का फ़ैसला खुद करता है और इसकी जानकारीColumnको देता है.
- दूसरे
Column, बच्चे के मेज़रमेंट का इस्तेमाल करके अपना साइज़ तय करता है. यह अपने बच्चों की ज़्यादा से ज़्यादा चौड़ाई और उनकी ऊंचाई के योग का इस्तेमाल करता है.Columnअपने चाइल्ड विजेट को खुद के हिसाब से रखता है. साथ ही, उन्हें एक-दूसरे के नीचे वर्टिकल तरीके से रखता है.Row, बच्चे के मेज़रमेंट का इस्तेमाल करके अपना साइज़ तय करता है. यह चाइल्ड एलिमेंट की ज़्यादा से ज़्यादा ऊंचाई और उसकी चौड़ाई के योग का इस्तेमाल करता है. इसके बाद, यह अपने चाइल्ड नोड को जगह देता है.
ध्यान दें कि हर नोड पर सिर्फ़ एक बार जाया गया था. Compose के रनटाइम को सभी नोड को मेज़र करने और उन्हें जगह पर रखने के लिए, यूज़र इंटरफ़ेस (यूआई) ट्री से सिर्फ़ एक बार गुज़रना पड़ता है. इससे परफ़ॉर्मेंस बेहतर होती है. ट्री में नोड की संख्या बढ़ने पर, उसे ट्रैवर्स करने में लगने वाला समय भी बढ़ता है. इसके उलट, अगर हर नोड पर कई बार जाया जाता है, तो ट्रैवर्सल का समय तेज़ी से बढ़ता है.
ड्रॉइंग
ड्रॉइंग फ़ेज़ में, ट्री को फिर से ऊपर से नीचे की ओर ट्रैवर्स किया जाता है. साथ ही, हर नोड बारी-बारी से स्क्रीन पर खुद को ड्रॉ करता है.
पांचवीं इमेज. ड्राइंग फ़ेज़ में, स्क्रीन पर पिक्सल बनाए जाते हैं.
पिछले उदाहरण का इस्तेमाल करके, ट्री कॉन्टेंट को इस तरह से बनाया जाता है:
Rowमें मौजूद कॉन्टेंट को रेंडर किया जाता है. जैसे, बैकग्राउंड का रंग.Imageअपने-आप बन जाता है.Columnअपने-आप बन जाता है.- पहली और दूसरी
Textअपने-आप बन जाती हैं.
छठी इमेज. यूज़र इंटरफ़ेस (यूआई) ट्री और उसका ड्रॉ किया गया वर्शन.
स्टेट रीड
जब पिछले चरणों में से किसी एक चरण के दौरान, snapshot state का value पढ़ा जाता है, तो कंपोज़ अपने-आप यह ट्रैक करता है कि value पढ़ते समय वह क्या कर रहा था. इस ट्रैकिंग की मदद से, Compose, रीडर को तब फिर से चालू कर सकता है, जब value की स्थिति बदलती है. साथ ही, यह Compose में स्थिति की निगरानी करने का आधार है.
आम तौर पर, mutableStateOf() का इस्तेमाल करके स्टेट बनाई जाती है. इसके बाद, इसे दो तरीकों में से किसी एक तरीके से ऐक्सेस किया जाता है: value प्रॉपर्टी को सीधे तौर पर ऐक्सेस करके या Kotlin प्रॉपर्टी डेलिगेट का इस्तेमाल करके. इनके बारे में ज़्यादा जानने के लिए, कंपोज़ेबल में स्टेट लेख पढ़ें. इस गाइड के हिसाब से, "स्टेट रीड" का मतलब, ऐक्सेस करने के इन दोनों तरीकों में से कोई एक तरीका है.
// State read without property delegate. val paddingState: MutableState<Dp> = remember { mutableStateOf(8.dp) } Text( text = "Hello", modifier = Modifier.padding(paddingState.value) )
// State read with property delegate. var padding: Dp by remember { mutableStateOf(8.dp) } Text( text = "Hello", modifier = Modifier.padding(padding) )
property delegate के तहत, State के value को ऐक्सेस और अपडेट करने के लिए, "getter" और "setter" फ़ंक्शन का इस्तेमाल किया जाता है. ये गेटर और सेटर फ़ंक्शन, प्रॉपर्टी को वैल्यू के तौर पर रेफ़रंस करने पर ही लागू होते हैं. इन्हें प्रॉपर्टी बनाने के दौरान लागू नहीं किया जाता. यही वजह है कि ऊपर बताए गए दोनों तरीके एक जैसे हैं.
कोड का हर वह ब्लॉक जिसे रीड स्टेट में बदलाव होने पर फिर से एक्ज़ीक्यूट किया जा सकता है, रीस्टार्ट स्कोप होता है. Compose, अलग-अलग फ़ेज़ में valueस्टेट में होने वाले बदलावों और स्कोप को रीस्टार्ट करने की प्रोसेस को ट्रैक करता है.
फ़ेज़ के हिसाब से स्थिति का डेटा पढ़ना
जैसा कि पहले बताया गया है, Compose में तीन मुख्य फ़ेज़ होते हैं. Compose यह ट्रैक करता है कि इनमें से हर फ़ेज़ में किस स्थिति को पढ़ा गया है. इससे Compose को सिर्फ़ उन फ़ेज़ को सूचना देने की अनुमति मिलती है जिन्हें आपके यूज़र इंटरफ़ेस (यूआई) के हर प्रभावित एलिमेंट के लिए काम करना होता है.
यहां दिए गए सेक्शन में, हर फ़ेज़ के बारे में बताया गया है. साथ ही, यह भी बताया गया है कि किसी फ़ेज़ में स्टेट वैल्यू को पढ़ने पर क्या होता है.
पहला चरण: कंपोज़िशन
@Composable फ़ंक्शन या लैम्डा ब्लॉक में स्टेट को पढ़ने से कंपोज़िशन और बाद के चरणों पर असर पड़ता है. जब किसी स्टेट का value बदलता है, तो कंपोज़र, उन सभी कंपोज़ेबल फ़ंक्शन को फिर से चलाने का शेड्यूल बनाता है जो उस स्टेट के value को पढ़ते हैं. ध्यान दें कि अगर इनपुट में कोई बदलाव नहीं हुआ है, तो रनटाइम कुछ या सभी कंपोज़ेबल फ़ंक्शन को स्किप कर सकता है. ज़्यादा जानकारी के लिए, इनपुट में बदलाव न होने पर, टास्क को स्किप करना लेख पढ़ें.
कंपोज़िशन के नतीजे के आधार पर, Compose UI लेआउट और ड्रॉइंग फ़ेज़ चलाता है. अगर कॉन्टेंट में कोई बदलाव नहीं होता है और साइज़ और लेआउट में भी कोई बदलाव नहीं होता है, तो हो सकता है कि यह इन चरणों को छोड़ दे.
var padding by remember { mutableStateOf(8.dp) } Text( text = "Hello", // The `padding` state is read in the composition phase // when the modifier is constructed. // Changes in `padding` will invoke recomposition. modifier = Modifier.padding(padding) )
दूसरा चरण: लेआउट
लेआउट फ़ेज़ में दो चरण होते हैं: मेज़रमेंट और प्लेसमेंट. मेज़रमेंट का चरण, Layout कंपोज़ेबल को पास किए गए मेज़र लैंबडा को चलाता है. साथ ही, LayoutModifier इंटरफ़ेस के MeasureScope.measure तरीके को भी चलाता है.
प्लेसमेंट स्टेप, layout फ़ंक्शन के प्लेसमेंट ब्लॉक, Modifier.offset { … } के लैम्डा ब्लॉक, और इसी तरह के अन्य फ़ंक्शन को चलाता है.
इनमें से हर चरण के दौरान स्टेट को पढ़ने से लेआउट और संभावित रूप से ड्रॉइंग फ़ेज़ पर असर पड़ता है. जब स्थिति value बदलती है, तब Compose UI, लेआउट फ़ेज़ को शेड्यूल करता है. अगर साइज़ या पोज़िशन में बदलाव हुआ है, तो यह ड्रॉइंग फ़ेज़ को भी चलाता है.
var offsetX by remember { mutableStateOf(8.dp) } Text( text = "Hello", modifier = Modifier.offset { // The `offsetX` state is read in the placement step // of the layout phase when the offset is calculated. // Changes in `offsetX` restart the layout. IntOffset(offsetX.roundToPx(), 0) } )
तीसरा चरण: ड्राइंग
ड्रॉइंग कोड के दौरान स्टेट को पढ़ने से, ड्रॉइंग फ़ेज़ पर असर पड़ता है. सामान्य उदाहरणों में Canvas(), Modifier.drawBehind, और Modifier.drawWithContent शामिल हैं. जब स्थिति में value बदलाव होता है, तब Compose UI सिर्फ़ ड्रॉ फ़ेज़ को चलाता है.
var color by remember { mutableStateOf(Color.Red) } Canvas(modifier = modifier) { // The `color` state is read in the drawing phase // when the canvas is rendered. // Changes in `color` restart the drawing. drawRect(color) }
Optimize की स्थिति को पढ़ने की सुविधा
Compose, स्थानीय तौर पर स्टेट रीड ट्रैकिंग करता है. इसलिए, हर स्टेट को सही फ़ेज़ में पढ़कर, किए गए काम की मात्रा को कम किया जा सकता है.
यहां दिया गया उदाहरण देखें. इस उदाहरण में एक Image() है, जो अपनी फ़ाइनल लेआउट पोज़िशन को ऑफ़सेट करने के लिए, ऑफ़सेट मॉडिफ़ायर का इस्तेमाल करता है. इससे उपयोगकर्ता के स्क्रोल करने पर, पैरलैक्स इफ़ेक्ट मिलता है.
Box { val listState = rememberLazyListState() Image( // ... // Non-optimal implementation! Modifier.offset( with(LocalDensity.current) { // State read of firstVisibleItemScrollOffset in composition (listState.firstVisibleItemScrollOffset / 2).toDp() } ) ) LazyColumn(state = listState) { // ... } }
यह कोड काम करता है, लेकिन इससे परफ़ॉर्मेंस अच्छी नहीं मिलती. लिखे गए कोड के मुताबिक, यह firstVisibleItemScrollOffset स्टेट के value को पढ़ता है और उसे Modifier.offset(offset: Dp) फ़ंक्शन को पास करता है. उपयोगकर्ता के स्क्रोल करने पर, firstVisibleItemScrollOffset का value बदल जाएगा. जैसा कि आपने सीखा, Compose किसी भी स्टेट को ट्रैक करता है, ताकि वह पढ़ने वाले कोड को फिर से शुरू कर सके. इस उदाहरण में, यह कोड Box का कॉन्टेंट है.
यह कंपोज़िशन फ़ेज़ में किसी स्थिति को पढ़ने का उदाहरण है. यह ज़रूरी नहीं है कि यह कोई बुरी बात हो. दरअसल, यह रीकंपोज़िशन का आधार है. इससे डेटा में हुए बदलावों के आधार पर नया यूज़र इंटरफ़ेस (यूआई) जनरेट किया जा सकता है.
अहम जानकारी: यह उदाहरण सही नहीं है, क्योंकि हर स्क्रोल इवेंट की वजह से, पूरे कंपोज़ेबल कॉन्टेंट का फिर से आकलन किया जाता है. साथ ही, उसे मेज़र किया जाता है, लेआउट किया जाता है, और आखिर में ड्रॉ किया जाता है. हर स्क्रोल पर कंपोज़ फ़ेज़ ट्रिगर होता है. भले ही, दिखाए गए कॉन्टेंट में कोई बदलाव न हुआ हो, सिर्फ़ उसकी जगह बदली हो. लेआउट फ़ेज़ को सिर्फ़ फिर से ट्रिगर करने के लिए, स्टेट को ऑप्टिमाइज़ किया जा सकता है.
lambda की मदद से ऑफ़सेट करना
ऑफ़सेट मॉडिफ़ायर का एक और वर्शन उपलब्ध है:
Modifier.offset(offset: Density.() -> IntOffset).
इस वर्शन में लैम्डा पैरामीटर का इस्तेमाल किया जाता है. इसमें लैम्डा ब्लॉक, नतीजे के तौर पर ऑफ़सेट दिखाता है. इस कोड का इस्तेमाल करने के लिए, इसे अपडेट करें:
Box { val listState = rememberLazyListState() Image( // ... Modifier.offset { // State read of firstVisibleItemScrollOffset in Layout IntOffset(x = 0, y = listState.firstVisibleItemScrollOffset / 2) } ) LazyColumn(state = listState) { // ... } }
तो फिर, यह ज़्यादा बेहतर परफ़ॉर्म क्यों करता है? मॉडिफ़ायर को दिया गया लैम्डा ब्लॉक, लेआउट फ़ेज़ के दौरान (खास तौर पर, लेआउट फ़ेज़ के प्लेसमेंट चरण के दौरान) लागू होता है. इसका मतलब है कि कंपोज़िशन के दौरान, firstVisibleItemScrollOffset स्टेट को अब नहीं पढ़ा जाता. Compose, यह ट्रैक करता है कि स्टेट को कब पढ़ा गया. इसलिए, इस बदलाव का मतलब है कि अगर firstVisibleItemScrollOffset का value बदलता है, तो Compose को सिर्फ़ लेआउट और ड्रॉइंग फ़ेज़ को रीस्टार्ट करना होगा.
ज़रूर, कंपोज़िशन फ़ेज़ में अक्सर स्थितियों को पढ़ना बहुत ज़रूरी होता है. हालांकि, ऐसे मामले भी होते हैं जिनमें स्टेट में होने वाले बदलावों को फ़िल्टर करके, फिर से कंपोज़ होने की संख्या को कम किया जा सकता है. इसके बारे में ज़्यादा जानने के लिए, derivedStateOf: एक या एक से ज़्यादा स्टेट ऑब्जेक्ट को किसी दूसरी स्टेट में बदलना लेख पढ़ें.
रीकंपोज़िशन लूप (साइक्लिक फ़ेज़ डिपेंडेंसी)
इस गाइड में पहले बताया गया था कि Compose के फ़ेज़ हमेशा एक ही क्रम में लागू होते हैं. साथ ही, यह भी बताया गया था कि एक ही फ़्रेम में वापस नहीं जाया जा सकता. हालांकि, इससे ऐप्लिकेशन को अलग-अलग फ़्रेम में कंपोज़िशन लूप में जाने से नहीं रोका जा सकता. इस उदाहरण से समझें:
Box { var imageHeightPx by remember { mutableIntStateOf(0) } Image( painter = painterResource(R.drawable.rectangle), contentDescription = "I'm above the text", modifier = Modifier .fillMaxWidth() .onSizeChanged { size -> // Don't do this imageHeightPx = size.height } ) Text( text = "I'm below the image", modifier = Modifier.padding( top = with(LocalDensity.current) { imageHeightPx.toDp() } ) ) }
इस उदाहरण में, वर्टिकल कॉलम का इस्तेमाल किया गया है. इसमें इमेज सबसे ऊपर और टेक्स्ट उसके नीचे है. यह इमेज के तय किए गए साइज़ को पाने के लिए Modifier.onSizeChanged() का इस्तेमाल करता है. इसके बाद, टेक्स्ट को नीचे की ओर ले जाने के लिए, टेक्स्ट पर Modifier.padding() का इस्तेमाल करता है.
Px से Dp में अचानक हुए बदलाव से पता चलता है कि कोड में कोई समस्या है.
इस उदाहरण में समस्या यह है कि कोड, एक ही फ़्रेम में "फ़ाइनल" लेआउट पर नहीं पहुंचता. यह कोड, कई फ़्रेम पर निर्भर करता है. इससे गैर-ज़रूरी काम होता है. साथ ही, उपयोगकर्ता के लिए स्क्रीन पर यूज़र इंटरफ़ेस (यूआई) इधर-उधर घूमता रहता है.
पहले फ़्रेम की कंपोज़िशन
पहले फ़्रेम के कंपोज़िशन फ़ेज़ के दौरान, imageHeightPx शुरू में 0 होता है. इसलिए, कोड में Modifier.padding(top = 0) के साथ टेक्स्ट दिया गया है.
इसके बाद, लेआउट फ़ेज़ में onSizeChanged मॉडिफ़ायर का कॉलबैक शुरू होता है. यह imageHeightPx को इमेज की असल ऊंचाई के हिसाब से अपडेट करता है. यह फ़ंक्शन, अगले फ़्रेम के लिए फिर से कंपोज़ करने की प्रोसेस को शेड्यूल करता है. हालांकि, मौजूदा ड्रॉइंग फ़ेज़ के दौरान, टेक्स्ट 0 की पैडिंग के साथ रेंडर होता है. ऐसा इसलिए होता है, क्योंकि अपडेट की गई imageHeightPx वैल्यू अभी तक नहीं दिखाई गई है.
दूसरी फ़्रेम कंपोज़िशन
Compose, दूसरे फ़्रेम को शुरू करता है. यह imageHeightPx की वैल्यू में बदलाव होने पर ट्रिगर होता है. इस फ़्रेम की कंपोज़िशन फ़ेज़ में, Box कॉन्टेंट ब्लॉक में स्थिति पढ़ी जाती है. अब टेक्स्ट को पैडिंग के साथ दिखाया जाता है. यह पैडिंग, इमेज की ऊंचाई से मेल खाती है. लेआउट फ़ेज़ के दौरान, imageHeightPx को फिर से सेट किया जाता है. हालांकि, वैल्यू में कोई बदलाव न होने की वजह से, दोबारा कंपोज़ करने का कोई और शेड्यूल नहीं किया जाता.
यह उदाहरण बनावटी लग सकता है, लेकिन इस सामान्य पैटर्न से सावधान रहें:
Modifier.onSizeChanged(),onGloballyPositioned()या कुछ अन्य लेआउट ऑपरेशन- कुछ स्थिति अपडेट करें
- उस स्थिति का इस्तेमाल, लेआउट मॉडिफ़ायर (
padding(),height()या इसी तरह के अन्य मॉडिफ़ायर) के इनपुट के तौर पर करें - दोहराया जा सकता है
ऊपर दिए गए सैंपल में, लेआउट प्रिमिटिव का सही तरीके से इस्तेमाल करके समस्या को ठीक किया गया है. ऊपर दिए गए उदाहरण को Column() की मदद से लागू किया जा सकता है. हालांकि, आपके पास कोई ऐसा उदाहरण हो सकता है जिसके लिए कस्टम लेआउट की ज़रूरत हो. ऐसे में, आपको कस्टम लेआउट लिखना होगा. ज़्यादा जानकारी के लिए, कस्टम लेआउट गाइड देखें.
यहां सामान्य सिद्धांत यह है कि एक से ज़्यादा यूज़र इंटरफ़ेस (यूआई) एलिमेंट के लिए, एक ही भरोसेमंद सोर्स होना चाहिए. इन एलिमेंट को एक-दूसरे के हिसाब से मेज़र और प्लेस किया जाना चाहिए. सही लेआउट प्रिमिटिव का इस्तेमाल करने या कस्टम लेआउट बनाने का मतलब है कि कम से कम शेयर किया गया पैरंट, भरोसेमंद सोर्स के तौर पर काम करता है. यह कई एलिमेंट के बीच के संबंध को मैनेज कर सकता है. डाइनैमिक स्थिति को लागू करने से, इस सिद्धांत का उल्लंघन होता है.
रीकंपोज़िशन लूप और अलग-अलग फ़ेज़ में स्टेट को लिखने से बचने के तरीके के बारे में ज़्यादा जानने के लिए, Compose में बैकवर्ड राइटिंग लेख पढ़ें.
आपके लिए सुझाव
- ध्यान दें: JavaScript बंद होने पर लिंक का टेक्स्ट दिखता है
- स्टेट और Jetpack Compose
- सूचियां और ग्रिड
- Jetpack Compose के लिए Kotlin