Jetpack Compose के चरण

ज़्यादातर यूज़र इंटरफ़ेस (यूआई) टूलकिट की तरह, Compose कई यूज़र इंटरफ़ेस (यूआई) टूलकिट के ज़रिए फ़्रेम रेंडर करता है. अलग-अलग चरण शामिल करें. Android View सिस्टम को देखने पर, आपको तीन मुख्य चरण: माप, लेआउट, और ड्रॉइंग. कंपोज़ की सुविधा काफ़ी मिलती-जुलती है, लेकिन इसमें पहले से एक महत्वपूर्ण अतिरिक्त चरण है, जिसे शुरुआत में कंपोज़िशन कहते हैं.

कंपोज़िशन के बारे में, हमारे Compose के दस्तावेज़ में बताया गया है. इसमें सोच-समझकर कॉन्टेंट बनाना भी शामिल है लिखें और State और Jetpack Compose चुनें.

फ़्रेम के तीन फ़ेज़

लिखने के तीन मुख्य चरण होते हैं:

  1. कंपोज़िशन: क्या यूज़र इंटरफ़ेस (यूआई) दिखाना है. कंपोज़ेबल, फ़ंक्शन, और आपके यूज़र इंटरफ़ेस (यूआई) का ब्यौरा बनाता है.
  2. लेआउट: यूज़र इंटरफ़ेस (यूआई) को कहां करना है. इस चरण में दो चरण हैं: मेज़रमेंट और प्लेसमेंट के बारे में ज़्यादा जानें. लेआउट एलिमेंट, खुद को मेज़र करते हैं और उनकी जगह तय करते हैं लेआउट ट्री के हर नोड के लिए 2D निर्देशांक में कोई चाइल्ड एलिमेंट.
  3. ड्रॉइंग: कैसे रेंडर होती है. यूज़र इंटरफ़ेस (यूआई) एलिमेंट, कैनवस में खुलते हैं, आम तौर पर डिवाइस की स्क्रीन.
तीन चरणों की इमेज, जिसमें Compose में डेटा को यूज़र इंटरफ़ेस (यूआई) में बदला जाता है. जैसे, डेटा, कंपोज़िशन, लेआउट, ड्रॉइंग, यूज़र इंटरफ़ेस (यूआई).
पहली इमेज. तीन चरणों में, Compose में डेटा को यूज़र इंटरफ़ेस (यूआई) में बदला जाता है.

इन चरणों का क्रम आम तौर पर एक जैसा होता है. इससे डेटा को एक कंपोज़िशन से लेकर लेआउट तक और फ़्रेम बनाने के लिए ड्रॉइंग तक (जिसे यह भी जाना जाता है) एकतरफ़ा डेटा फ़्लो के तौर पर). BoxWithConstraints और LazyColumn और LazyRow को टैग किया जाता है अपवाद, जहां इसके बच्चों की संरचना माता-पिता के लेआउट के हिसाब से तय की जाती है फ़ेज़.

इस बात का अंदाज़ा लगाया जा सकता है कि ये तीन चरण, हर फ़्रेम के लिए वर्चुअल तरीके से होते हैं, हालांकि, परफ़ॉर्मेंस को ध्यान में रखते हुए, Compose में ऐसी क्वेरी को बार-बार करने से बचा जाता है जो इन सभी चरणों में एक जैसे इनपुट से समान नतीजों की गणना कर सकते हैं. लिखें कंपोज़ेबल चलाने के लिए स्किप फ़ंक्शन फ़ंक्शन को तब सक्रिय करें, जब वह किसी पुराने परिणाम का फिर से उपयोग कर सके और 'लिखें' यूज़र इंटरफ़ेस (यूआई) फिर से लेआउट न करे या अगर ज़रूरत न हो, तो पूरे पेड़ को फिर से ड्रॉ करें. कंपोज़ सिर्फ़ यह काम करता है: यूज़र इंटरफ़ेस (यूआई) को अपडेट करने के लिए, इस बारे में कम से कम ज़रूरत है. यह ऑप्टिमाइज़ेशन संभव है ऐसा इसलिए, क्योंकि ट्रैक को कंपोज़ करने की सुविधा की स्थिति को अलग-अलग चरणों में पढ़ा जाता है.

अलग-अलग चरणों को समझें

इस सेक्शन में बताया गया है कि कंपोज़ेबल के लिए, कंपोज़ की तीन चरणों को कैसे लागू किया जाता है पढ़ें.

कंपोज़िशन

कंपोज़िशन फ़ेज़ में, कंपोज़ रनटाइम, कंपोज़ेबल फ़ंक्शन को एक्ज़ीक्यूट करता है और आपके यूज़र इंटरफ़ेस (यूआई) को दिखाने वाला ट्री स्ट्रक्चर दिखाता है. इस यूज़र इंटरफ़ेस (यूआई) ट्री में यह शामिल है ऐसे लेआउट नोड जिनमें अगले चरणों के लिए ज़रूरी सारी जानकारी मौजूद होती है. जैसे नीचे दिए गए वीडियो में दिखाए गए हैं:

दूसरा डायग्राम. कंपोज़िशन में बनाए गए आपके यूज़र इंटरफ़ेस (यूआई) को दिखाने वाला ट्री फ़ेज़.

कोड और यूज़र इंटरफ़ेस (यूआई) ट्री का सब-सेक्शन इस तरह दिखता है:

एक कोड स्निपेट, जिसमें पांच कंपोज़ेबल और यूज़र इंटरफ़ेस (यूआई) ट्री होता है. इस कोड स्निपेट में, चाइल्ड नोड अपने पैरंट नोड से ब्रांच होते हैं.
तीसरी इमेज. यूज़र इंटरफ़ेस (यूआई) ट्री का सब-सेक्शन, जिसमें उनसे जुड़ा कोड मौजूद है.

इन उदाहरणों में, कोड में मौजूद हर कंपोज़ेबल फ़ंक्शन को एक लेआउट में मैप किया गया है नोड को यूज़र इंटरफ़ेस ट्री में डालें. ज़्यादा मुश्किल उदाहरणों के लिए, कंपोज़ेबल में लॉजिक और और अलग-अलग स्थितियों के आधार पर एक अलग ट्री बनाएं.

लेआउट

लेआउट फ़ेज़ में, कंपोज़िशन के कंपोज़िशन फ़ेज़ में तैयार यूज़र इंटरफ़ेस (यूआई) ट्री का इस्तेमाल किया जाता है इनपुट के रूप में. लेआउट नोड के कलेक्शन में वह सारी जानकारी होती है जो 2D स्पेस में हर नोड का साइज़ और जगह तय करना.

चौथी इमेज. लेआउट फ़ेज़ के दौरान, यूज़र इंटरफ़ेस (यूआई) ट्री में हर लेआउट नोड का मेज़रमेंट और प्लेसमेंट.

लेआउट फ़ेज़ के दौरान, नीचे दिए गए तीन चरणों का इस्तेमाल करके ट्री को एक्सप्लोर किया जाता है एल्गोरिदम:

  1. चिल्ड्रेन को मापें: अगर कोई नोड मौजूद है, तो नोड अपने चिल्ड्रन को मापता है.
  2. अपने हिसाब से साइज़ तय करना: इन मेज़रमेंट के आधार पर, नोड अपने-आप तय करता है साइज़.
  3. प्लेस चिल्ड्रन (बच्चे की जगह): हर चाइल्ड नोड को नोड के पैमाने पर रखा जाता है स्थिति.

इस फ़ेज़ के आखिर में, हर लेआउट नोड में ये चीज़ें होती हैं:

  • असाइन की गई width और height
  • एक x, y कोऑर्डिनेट जहां इसे बनाया जाना चाहिए

पिछले सेक्शन से यूज़र इंटरफ़ेस (यूआई) ट्री को वापस लाएं:

पांच कंपोज़ेबल और यूज़र इंटरफ़ेस (यूआई) ट्री वाला एक कोड स्निपेट, जिसमें चाइल्ड नोड अपने पैरंट नोड से ब्रांचिंग करते हैं

इस ट्री के लिए, एल्गोरिदम इस तरह काम करता है:

  1. Row अपने चाइल्ड, Image और Column को मापता है.
  2. Image मापा जाता है. इसका कोई बच्चा नहीं है, इसलिए यह अपने हिसाब से तय करती है साइज़ और उसे Row पर वापस रिपोर्ट कर देता है.
  3. इसके बाद, Column को मापा जाता है. यह अपने बच्चों को मापता है (दो Text कंपोज़ेबल).
  4. पहले Text को मापा जाता है. इसका कोई बच्चा नहीं है, इसलिए यह तय करता है कि और अपने आकार को Column पर वापस रिपोर्ट करता है.
    1. दूसरे Text को मापा जाता है. इसका कोई बच्चा नहीं है, इसलिए यह तय करता है कि और उसे Column पर वापस रिपोर्ट करता है.
  5. Column अपने हिसाब से साइज़ तय करने के लिए, चाइल्ड मेज़रमेंट का इस्तेमाल करता है. यह अधिकतम चाइल्ड चौड़ाई और इसकी चिल्ड्रन की ऊंचाई का योग.
  6. Column अपने बच्चों से उनकी तुलना करता है और उन्हें नीचे रखता है एक-दूसरे को वर्टिकल तौर पर कनेक्ट करते हैं.
  7. Row अपने हिसाब से साइज़ तय करने के लिए, चाइल्ड मेज़रमेंट का इस्तेमाल करता है. यह अधिकतम चाइल्ड ऊंचाई और इसके बच्चों की चौड़ाई का योग. इसके बाद, यह अपने बच्चे.

ध्यान दें कि हर नोड सिर्फ़ एक बार विज़िट किया गया है. लिखने के लिए रनटाइम के लिए सिर्फ़ एक की ज़रूरत होती है सभी नोड को मापने और उन्हें व्यवस्थित करने के लिए, यूआई ट्री से गुज़रते हैं. इससे बेहतर होता है परफ़ॉर्मेंस. जब ट्री में नोड की संख्या बढ़ जाती है, तो इसका एक रेखीय तरीके से बढ़ जाता है. इसके उलट, अगर हर नोड कई बार विज़िट किया जाता है, तो ट्रैवर्सल समय बहुत तेज़ी से बढ़ जाता है.

ड्रॉइंग

बनाने की प्रक्रिया में, पेड़ को फिर से ऊपर से नीचे की ओर दिखाया जाता है और हर नोड, स्क्रीन पर खुद को खींचता है.

पांचवी इमेज. ड्रॉइंग का चरण, स्क्रीन पर पिक्सल खींचता है.

ऊपर दिए गए उदाहरण का इस्तेमाल करके, ट्री के कॉन्टेंट को इस तरह से ड्रॉ किया गया है:

  1. Row अपनी पसंद का कोई भी कॉन्टेंट खींचता है, जैसे कि बैकग्राउंड का रंग.
  2. Image खुद को आकर्षित करता है.
  3. Column खुद को आकर्षित करता है.
  4. पहला और दूसरा Text खुद ड्रॉ करते हैं.

छठी इमेज. यूज़र इंटरफ़ेस (यूआई) ट्री और उसे दिखाया गया.

स्टेट रीड

जब किसी अवधि के दौरान स्नैपशॉट स्टेट की वैल्यू पढ़ी जाती है यह सुविधा चालू करते समय, अपने-आप ट्रैक करती है कि वैल्यू को पढ़ा गया. इस ट्रैकिंग से, Compose की सुविधा का इस्तेमाल करके पाठक को मैसेज फिर से चलाया जा सकता है. ऐसा तब होता है, जब स्टेट वैल्यू में बदलाव होता है और यह 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)
)

प्रॉपर्टी के हुड के तहत जिस व्यक्ति को ईमेल खाते का ऐक्सेस देना है, "गेटर" और "सेटर" फ़ंक्शन का इस्तेमाल, राज्य के value. ये गैटर और सेटर फ़ंक्शन सिर्फ़ तब शुरू होते हैं, जब आपने रेफ़रंस के तौर पर प्रॉपर्टी को वैल्यू के तौर पर इस्तेमाल किया जाता है, न कि प्रॉपर्टी को बनाने पर. इसलिए, दोनों तरीकों से ऊपर दी गई वैल्यू एक जैसी है.

कोड का हर एक ब्लॉक जिसे रीड स्टेट बदलने पर फिर से लागू किया जा सकता है फिर से शुरू करने का दायरा. कंपोज़ की सुविधा की मदद से, वैल्यू में होने वाले बदलावों को ट्रैक किया जाता है और फिर से शुरू किया जाता है दायरे में रहते हैं.

चरणबद्ध तरीके से पढ़ने की सुविधा

जैसा कि ऊपर बताया गया है, ट्रैक लिखने और लिखने की सुविधा के तीन मुख्य चरण हैं इनमें से हर स्थिति को कौनसी स्थिति में पढ़ा जा सकता है. इससे कंपोज़ की मदद से सिर्फ़ चरण पूरे करने हैं, जो आपके हर उस एलिमेंट के लिए काम करेंगे जिस पर असर पड़ा है यूज़र इंटरफ़ेस (यूआई).

आइए, हर चरण को देखें और बताएं कि किसी राज्य की वैल्यू को पढ़ने पर क्या होता है शामिल करें.

पहला चरण: कंपोज़िशन

@Composable फ़ंक्शन या लैम्डा ब्लॉक के अंदर लिखा गया स्टेटस कंपोज़िशन पर असर डालता है और संभावित रूप से बाद के चरण पूरे करने में मदद मिलेगी. जब इस स्थिति की वैल्यू बदलती है, तो रीकंपोज़र उन सभी कंपोज़ेबल फ़ंक्शन को दोबारा चलाने के लिए शेड्यूल करता है जो राज्य का मान. ध्यान दें कि रनटाइम के दौरान, ऐसा हो सकता है कि रनटाइम के दौरान, कंपोज़ेबल फ़ंक्शन का इस्तेमाल कर सकता है. अगर इनपुट शामिल नहीं हैं, तो स्किप करना देखें नहीं बदला है.

कंपोज़िशन के नतीजे के आधार पर, 'लिखें' यूज़र इंटरफ़ेस (यूआई) लेआउट और ड्रॉइंग चलाता है फ़ेज़. अगर कॉन्टेंट पहले जैसा बना रहता है और साइज़ में बदलाव नहीं होता है, तो इन चरणों को पूरा नहीं किया जा सकता और लेआउट नहीं बदलेगा.

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 कंपोज़ेबल को पास किया गया माप लैम्डा करता है, MeasureScope.measure तरीका LayoutModifier इंटरफ़ेस की बनाई और इसी तरह जारी रहेगा. कॉन्टेंट बनाने प्लेसमेंट चरण, layout फ़ंक्शन, लैम्डा के प्लेसमेंट ब्लॉक को चलाता है Modifier.offset { … } का ब्लॉक वगैरह.

इनमें से हर चरण के दौरान, पढ़ने की स्थिति का असर लेआउट पर पड़ता है और हो सकता है कि ड्रॉइंग फ़ेज़. स्टेटस में बदलाव होने पर, Compose का यूज़र इंटरफ़ेस (यूआई) लेआउट को शेड्यूल करता है फ़ेज़. साइज़ या पोज़िशन बदलने पर, यह ड्रॉइंग का चरण भी चलाता है.

ज़्यादा सटीक जानकारी के लिए, मेज़रमेंट का तरीका और प्लेसमेंट का चरण अलग-अलग होते हैं स्कोप को फिर से चालू करता है, इसका मतलब है कि प्लेसमेंट चरण में पढ़ने की स्थिति, फिर से शुरू नहीं होती से पहले वाला चरण देखें. हालांकि, ये दो चरण अक्सर आपस में जुड़े हुए हों, इसलिए प्लेसमेंट चरण में पढ़े जाने की स्थिति से दूसरे रीस्टार्ट होने पर असर पड़ सकता है वे दायरे जो मेज़रमेंट चरण से जुड़े हैं.

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 शामिल हैं. टास्क कब शुरू होगा स्थिति की वैल्यू बदलने पर, 'लिखें' यूज़र इंटरफ़ेस (यूआई) सिर्फ़ ड्रॉ के चरण को पूरा करता है.

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)
}

ऑप्टिमाइज़ करने की स्थिति में पढ़ने की सुविधा

कंपोज़ की सुविधा की मदद से, स्थानीय भाषा के हिसाब से डेटा को ट्रैक किया जा सकता है. इससे हम कम से कम समय में हर राज्य को एक सही चरण में पढ़कर परफ़ॉर्म किया गया.

आइए, एक उदाहरण देखें. यहां हमारे पास एक 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 स्थिति की वैल्यू को पढ़ता है और उसे यह Modifier.offset(offset: Dp) फ़ंक्शन का इस्तेमाल करना होगा. जब उपयोगकर्ता स्क्रोल करेगा, तब firstVisibleItemScrollOffset वैल्यू बदलें. जैसा कि हम जानते हैं, कंपोज़ की सुविधा हर टेक्स्ट को ट्रैक करती है, ताकि वह रीस्टार्ट हो सके (फिर से शुरू करें) रीडिंग कोड, जो हमारे उदाहरण में Box.

यह कंपोज़िशन फ़ेज़ में पढ़े जा रहे स्टेट का उदाहरण है. यह है कोई बुरी बात नहीं है. असल में, चीज़ों की बनावट और ज़रूरत के मुताबिक, इससे डेटा में बदलाव करके, नया यूआई लागू किया जा सकता है.

इस उदाहरण में, हालांकि यह बेहतर नहीं है, क्योंकि हर स्क्रोल इवेंट का नतीजा कंपोज़ेबल में तैयार किए गए कॉन्टेंट की फिर से समीक्षा की जाएगी. इसके बाद, आकलन किया जाएगा और बनाई गई और आखिर में बनाई गई. हम हर बार स्क्रोल करने पर, लिखें फ़ेज़ को ट्रिगर कर रहे हैं भले ही, हम जो दिखा रहे हैं वह बदला नहीं है. यह बदलाव सिर्फ़ कहां दिखाया जा रहा है. हम सिर्फ़ लेआउट फ़ेज़ को फिर से ट्रिगर करने के लिए, रीड की स्थिति को ऑप्टिमाइज़ कर सकते हैं.

ऑफ़सेट मॉडिफ़ायर का एक और वर्शन उपलब्ध है: 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) {
        // ...
    }
}

इसकी परफ़ॉर्मेंस अच्छी क्यों है? कार्रवाई बदलने वाली कुंजी के लिए, हमने जो Lambda ब्लॉक दिया है वह है लेआउट फ़ेज़ के दौरान शुरू किया जाता है. खास तौर पर, लेआउट फ़ेज़ के दौरान प्लेसमेंट चरण), इसका मतलब है कि हमारा firstVisibleItemScrollOffset राज्य कोई कंपोज़िशन के दौरान ज़्यादा समय तक पढ़ा जाता है. क्योंकि स्थिति पढ़ ली जाने पर ट्रैक लिखें, इस बदलाव का मतलब है कि अगर firstVisibleItemScrollOffset की वैल्यू में बदलाव होता है, लिखने के लिए सिर्फ़ लेआउट और ड्रॉइंग के चरणों को रीस्टार्ट करना होगा.

यह उदाहरण अलग-अलग ऑफ़सेट मॉडिफ़ायर पर निर्भर करता है, ताकि नतीजे में बदलने वाले कोड का इस्तेमाल कर सकते हैं, लेकिन आम बात यह है कि: यह सबसे कम संभावित चरण होता है. इसकी मदद से, कंपोज़ की सुविधा में तय की गई कम से कम काम.

कंपोज़िशन में राज्यों को पढ़ना बहुत ज़रूरी है फ़ेज़. फिर भी, ऐसे मामले हैं जहां हम अपनी ऑनलाइन गतिविधि स्थिति में हुए बदलावों को फ़िल्टर करके, कैंपेन में बदलाव करना. इस बारे में ज़्यादा जानकारी पाने के लिए, derivedStateOf: एक या एक से ज़्यादा स्टेट ऑब्जेक्ट को दूसरे में कन्वर्ट करें राज्य के हिसाब से सही है.

लूप में बदलाव करने की सुविधा (साइकिक फ़ेज़ डिपेंडेंसी)

पहले हमने बताया था कि कंपोज़ की सुविधा के चरण हमेशा एक ही क्रम में रखें और यह कि एक ही फ़्रेम में रहते हुए पीछे जाने का कोई तरीका नहीं है. हालांकि, इससे ऐप्लिकेशन को कंपोज़िशन लूप में जाने से नहीं रोका जाता अलग-अलग फ़्रेम का इस्तेमाल करें. इस उदाहरण से समझें:

Box {
    var imageHeightPx by remember { mutableStateOf(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. बॉक्स के कॉन्टेंट ब्लॉक में राज्य को पढ़ा जाता है और उसे शुरू कर दिया जाता है कंपोज़िशन वाले चरण में. इस बार, टेक्स्ट को पैडिंग (जगह) के साथ दिया जाता है और इमेज की ऊंचाई से मेल खा रहा है. लेआउट फ़ेज़ में, कोड imageHeightPx फिर से, लेकिन वैल्यू के बाद से कोई बदलाव शेड्यूल नहीं किया गया है पहले जैसा ही रहेगा.

आखिर में, हमें टेक्स्ट पर मनचाही पैडिंग मिलती है, लेकिन यह पैडिंग वैल्यू को वापस किसी दूसरे फ़ेज़ में पास करने के लिए, एक अतिरिक्त फ़्रेम खर्च करना होगा और इसके नतीजे में, ओवरलैप होने वाले कॉन्टेंट के साथ एक फ़्रेम तैयार हो जाएगा.

यह उदाहरण बनावटी लग सकता है, लेकिन इस सामान्य पैटर्न को लेकर सावधान रहें:

  • Modifier.onSizeChanged(), onGloballyPositioned() या कुछ अन्य लेआउट कार्रवाइयां
  • कुछ स्थिति अपडेट करें
  • उस स्थिति का इस्तेमाल लेआउट मॉडिफ़ायर (padding(),height() या मिलते-जुलते)
  • संभावित तौर पर दोहराए जा सकते हैं

ऊपर दिए गए सैंपल को ठीक करने के लिए, सही लेआउट प्रिमिटिव का इस्तेमाल किया गया है. उदाहरण के लिए को एक आसान Column() से लागू किया जा सकता है, लेकिन हो सकता है कि आपके पास ज़्यादा जटिल उदाहरण के लिए, जिसमें कुछ कस्टम की आवश्यकता होती है, जिसके लिए कस्टम लेआउट. कस्टम लेआउट गाइड देखें हमारा वीडियो देखें.

यहां सामान्य सिद्धांत यह है कि एक से ज़्यादा यूज़र इंटरफ़ेस (यूआई) के लिए एक ही सोर्स हो ऐसे एलिमेंट जिन्हें एक-दूसरे के हिसाब से मापा और रखा जाना चाहिए. इसका इस्तेमाल किया जा रहा है या कस्टम लेआउट बनाने का मतलब है कि कम से कम शेयर किए गए माता-पिता, सच्चाई के स्रोत के तौर पर काम करते हैं और एक-दूसरे के साथ बेहतर तरीके से जुड़ते हैं एलिमेंट सेट अप करने की सुविधा मिलती है. गतिशील स्थिति का परिचय इस सिद्धांत को तोड़ता है.