कंपोज़ेबल का लाइफ़साइकल

इस पेज पर, आपको कॉम्पोज़ेबल के लाइफ़साइकल के बारे में जानकारी मिलेगी. साथ ही, यह भी पता चलेगा कि Compose यह कैसे तय करता है कि कॉम्पोज़ेबल को फिर से कॉम्पोज़ करने की ज़रूरत है या नहीं.

लाइफ़साइकल की खास जानकारी

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

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

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

कंपोज़ेबल के लाइफ़साइकल को दिखाने वाला डायग्राम

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

आम तौर पर, State<T> ऑब्जेक्ट में बदलाव होने पर, फिर से कॉम्पोज़ करने की प्रोसेस शुरू होती है. लिखें इन्हें ट्रैक करता है और कंपोज़ेबल में चलता है खास State<T> और कोई भी कंपोज़ेबल जिसे कॉल किया जा सकता हो स्किप किया.

अगर किसी कंपोज़ेबल को कई बार कॉल किया जाता है, तो कंपोज़िशन. कंपोज़िशन में हर कॉल का अपना लाइफ़साइकल होता है.

@Composable
fun MyComposable() {
    Column {
        Text("Hello")
        Text("World")
    }
}

पिछले कोड स्निपेट में एलिमेंट के क्रम को दिखाने वाला डायग्राम

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

कंपोज़िशन में मौजूद, कॉम्पोज़ेबल की बनावट

कॉम्पोज़िशन में किसी कॉम्पोज़ेबल के इंस्टेंस की पहचान, उसकी कॉल साइट से की जाती है. Compose कंपाइलर हर कॉल साइट को अलग मानता है. कॉल के लिए कंपोज़ेबल कई कॉल साइटों से, कंपोज़ेबल के कई इंस्टेंस कंपोज़िशन.

अगर डिज़ाइन करते समय, कंपोज़ेबल कॉल किया जाता है और वे पहले के मुकाबले अलग-अलग कंपोज़ेबल कॉल करते हैं पिछली कंपोज़ेबल में बनाए गए कौन-कौनसे कंपोज़ेबल थे कॉल किया गया या कॉल नहीं किया गया और उन कंपोज़ेबल के लिए जिन्हें दोनों भाषाओं में कॉल किया गया कंपोज़िशन इस्तेमाल नहीं किया है, तो कंपोज़िशन में इन्हें दोबारा नहीं डाला जाएगा. ऐसा तब होगा, जब उनके इनपुट में ऐसा न हो बदला गया.

साइड इफ़ेक्ट को उनके कॉम्पोज़ेबल से जोड़ने के लिए, पहचान को बनाए रखना ज़रूरी है, ताकि हर बार फिर से कॉम्पोज़ करने के बजाय, वे सही तरीके से पूरे हो सकें.

नीचे दिया गया उदाहरण देखें:

@Composable
fun LoginScreen(showError: Boolean) {
    if (showError) {
        LoginError()
    }
    LoginInput() // This call site affects where LoginInput is placed in Composition
}

@Composable
fun LoginInput() { /* ... */ }

@Composable
fun LoginError() { /* ... */ }

ऊपर दिए गए कोड स्निपेट में, LoginScreen शर्त के साथ LoginError कंपोज़ेबल और LoginInput कंपोज़ेबल को हमेशा कॉल किया जाएगा. हर कॉल के लिए, एक यूनीक कॉल साइट और सोर्स पोज़िशन चुनी गई है, जिसका इस्तेमाल कंपाइलर पहचानने में आसानी होती है.

इस डायग्राम में दिखाया गया है कि showError फ़्लैग को &#39;सही&#39; पर सेट करने पर, पहले के कोड को फिर से कैसे बनाया जाता है. LoginError कॉम्पोज़ेबल जोड़ा गया है, लेकिन अन्य कॉम्पोज़ेबल फिर से कॉम्पोज़ नहीं किए गए हैं.

तीसरी इमेज. राज्य के कंपोज़िशन में LoginScreen का प्रतिनिधित्व बदलाव होते हैं और एक रीकंपोज़िशन होता है. एक जैसे रंग का मतलब है कि उसे फिर से नहीं बनाया गया है.

भले ही, LoginInput को पहले कॉल किया गया हो, लेकिन बाद में दूसरा नाम मिला, LoginInput इंस्टेंस को बदलाव के दौरान सेव रखा जाएगा. इसके अलावा, क्योंकि LoginInput में ऐसा कोई पैरामीटर नहीं है जो बदल गया हो फिर से लिखें, LoginInput को किया गया कॉल कंपोज़ से स्किप कर दिया जाएगा.

स्मार्ट रीकंपोज़िशन की सुविधा को बेहतर बनाने के लिए ज़्यादा जानकारी जोड़ना

किसी कॉम्पोज़ेबल को कई बार कॉल करने पर, वह कंपोज़िशन में भी कई बार जुड़ जाएगा. जब किसी कॉल साइट से किसी कॉम्पोज़ेबल को कई बार कॉल किया जाता है, तो Compose के पास उस कॉम्पोज़ेबल के हर कॉल की यूनीक पहचान करने के लिए कोई जानकारी नहीं होती. इसलिए, इंस्टेंस को अलग-अलग रखने के लिए, कॉल साइट के साथ-साथ, लागू करने के क्रम का इस्तेमाल किया जाता है. कभी-कभी यह व्यवहार बेहद ज़रूरी होता है, लेकिन कुछ मामलों में इससे अनचाहा व्यवहार हो सकता है.

@Composable
fun MoviesScreen(movies: List<Movie>) {
    Column {
        for (movie in movies) {
            // MovieOverview composables are placed in Composition given its
            // index position in the for loop
            MovieOverview(movie)
        }
    }
}

ऊपर दिए गए उदाहरण में, Compose, कॉल साइट के साथ-साथ, कॉम्पोज़िशन में इंस्टेंस को अलग रखने के लिए, लागू करने के क्रम का इस्तेमाल करता है. अगर कोई नया movie जोड़ा जाता है सूची में सबसे नीचे तक लिखने के बाद, आप सूची में उनकी जगह नहीं बदली है. इसलिए, कंपोज़िशन में इन इंस्टेंस के लिए movie इनपुट एक जैसा ही है.

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

चौथी इमेज. नए कंपोज़िशन में MoviesScreen को दिखाना एलिमेंट को सूची में सबसे नीचे जोड़ा गया है. इसमें MovieOverview कंपोज़ेबल कंपोज़िशन को फिर से इस्तेमाल किया जा सकता है. MovieOverview में एक जैसे रंग का मतलब है, कंपोज़ेबल फिर से नहीं लिखा गया है.

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

@Composable
fun MovieOverview(movie: Movie) {
    Column {
        // Side effect explained later in the docs. If MovieOverview
        // recomposes, while fetching the image is in progress,
        // it is cancelled and restarted.
        val image = loadNetworkImage(movie.url)
        MovieHeader(image)

        /* ... */
    }
}

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

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

आम तौर पर, हम MovieOverview इंस्टेंस की पहचान इस तरह समझना चाहते हैं: को पास किए गए movie की पहचान से लिंक किया गया होता है. अगर हम फ़िल्मों की सूची का क्रम बदलते हैं, तो हम कॉम्पोज़िशन ट्री में मौजूद इंस्टेंस का क्रम भी इसी तरह बदल देंगे. ऐसा करने के बजाय, हम हर MovieOverview कॉम्पोज़ेबल को किसी दूसरी फ़िल्म के इंस्टेंस के साथ फिर से कॉम्पोज़ नहीं करेंगे. कंपोज़ की मदद से, रनटाइम के बारे में जानकारी हासिल की जा सकती है ट्री के किसी हिस्से की पहचान करने के लिए, आपको किन वैल्यू का इस्तेमाल करना है: key कंपोज़ेबल.

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

@Composable
fun MoviesScreenWithKey(movies: List<Movie>) {
    Column {
        for (movie in movies) {
            key(movie.id) { // Unique ID for this movie
                MovieOverview(movie)
            }
        }
    }
}

ऊपर बताए गए तरीके से, भले ही सूची में मौजूद एलिमेंट बदल जाएं, Compose MovieOverview के अलग-अलग कॉल को पहचानता है और उनका फिर से इस्तेमाल कर सकता है.

डायग्राम में दिखाया गया है कि अगर सूची में सबसे ऊपर कोई नया एलिमेंट जोड़ा जाता है, तो पिछले कोड को कैसे फिर से लिखा जाता है. आइटम की पहचान कुंजियों से की जाती है, इसलिए Compose को पता है कि उन्हें फिर से नहीं लिखना है, भले ही उनकी पोज़िशन बदल गई हो.

छठी इमेज. सूची में नया एलिमेंट जोड़ने पर, कॉम्पोज़िशन में MoviesScreen का दिखना. MovieOverview कॉम्पोज़ेबल में यूनीक बटन होते हैं. इसलिए, Compose यह पहचान लेता है कि किन MovieOverview इंस्टेंस में बदलाव नहीं हुआ है और उनका फिर से इस्तेमाल किया जा सकता है. साथ ही, उनके साइड इफ़ेक्ट लागू होते रहेंगे.

कुछ कंपोज़ेबल, key कंपोज़ेबल के साथ काम करते हैं. उदाहरण के लिए, LazyColumn, items डीएसएल में पसंद के मुताबिक key तय करने की मंज़ूरी देता है.

@Composable
fun MoviesScreenLazy(movies: List<Movie>) {
    LazyColumn {
        items(movies, key = { movie -> movie.id }) { movie ->
            MovieOverview(movie)
        }
    }
}

इनपुट में बदलाव न होने पर स्किप करना

बदलाव के दौरान, कंपोज़ेबल में मौजूद कुछ फ़ंक्शन में अगर उनके इनपुट पिछले निर्देश से नहीं बदले हैं, तो एक्ज़ीक्यूशन को पूरी तरह से स्किप कर दिया जाएगा कंपोज़िशन.

किसी कंपोज़ेबल फ़ंक्शन को स्किप किया जा सकता है, जब तक:

  • इस फ़ंक्शन में एक गैर-Unit रिटर्न टाइप है
  • फ़ंक्शन को @NonRestartableComposable या @NonSkippableComposable के साथ एनोटेट किया गया है
  • ज़रूरी पैरामीटर ऐसा है जो स्थिर नहीं है

स्ट्रॉन्ग स्किपिंग एक एक्सपेरिमेंटल कंपाइलर मोड है. इसमें आखिरी ज़रूरी शर्त को कम किया गया है.

किसी टाइप को स्थिर माना जा सके, इसके लिए उसे नीचे दिए गए समझौते का पालन करना होगा:

  • दो इंस्टेंस के लिए equals का नतीजा हमेशा एक ही रहेगा समान दो इंस्टेंस.
  • अगर इस टाइप की कोई सार्वजनिक प्रॉपर्टी बदलती है, तो कॉम्पोज़िशन को इसकी सूचना दी जाएगी.
  • सभी तरह की सार्वजनिक प्रॉपर्टी भी स्थिर हैं.

कुछ ज़रूरी सामान्य टाइप इस अनुबंध में आते हैं कंपोज़ कंपाइलर को स्टेबल माना जाएगा, भले ही वे साफ़ तौर पर @Stable एनोटेशन का इस्तेमाल करके, इसे स्थिर के तौर पर मार्क किया गया है:

  • सभी प्रिमिटिव वैल्यू टाइप: Boolean, Int, Long, Float, Char वगैरह.
  • स्ट्रिंग
  • सभी फ़ंक्शन टाइप (lambdas)

ये सभी टाइप, स्थिर कॉन्ट्रैक्ट का पालन कर सकते हैं, क्योंकि इनमें बदलाव नहीं किया जा सकता. इम्यूटेबल टाइप कभी नहीं बदलते, इसलिए उन्हें बदलाव के कॉम्पोज़िशन की सूचना कभी नहीं देनी पड़ती. इसलिए, इस कानूनी समझौते का पालन करना बहुत आसान होता है.

ध्यान दें कि एक तरह का फ़ॉर्मैट स्थिर है, लेकिन इसमें बदलाव किया जा सकता है. वह टाइप, Compose का MutableState है टाइप करें. अगर कोई वैल्यू MutableState में रखी जाती है, तो स्टेट ऑब्जेक्ट के बीच की कुल वैल्यू होगी को स्थिर माना जाता है, क्योंकि Compose में कोई बदलाव होने पर उसे सूचना दी जाएगी State की .value प्रॉपर्टी.

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

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

अगर Compose यह पता नहीं लगा पा रहा है कि कोई टाइप स्थिर है या नहीं, लेकिन आपको Compose को उसे स्थिर मानने के लिए मजबूर करना है, तो उसे @Stable एनोटेशन के साथ मार्क करें.

// Marking the type as stable to favor skipping and smart recompositions.
@Stable
interface UiState<T : Result<T>> {
    val value: T?
    val exception: Throwable?

    val hasError: Boolean
        get() = exception != null
}

ऊपर दिए गए कोड स्निपेट में, UiState एक इंटरफ़ेस है. इसलिए, Compose आम तौर पर इस टाइप को अस्थिर मान सकता है. @Stable एनोटेशन जोड़कर, Compose को बताया जाता है कि यह टाइप स्थिर है. इससे Compose, स्मार्ट रीकंपोज़िशन को प्राथमिकता दे पाता है. इसका यह भी मतलब है कि अगर इंटरफ़ेस का इस्तेमाल पैरामीटर टाइप के तौर पर किया जाता है, तो Compose अपने सभी लागू होने के तरीकों को स्थिर मानेगा.

फ़िलहाल कोई सुझाव नहीं है.

अपने Google खाते में करने की कोशिश करें.