स्थिरता से जुड़ी समस्याएं ठीक करना

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

स्किप करने की सुविधा को चालू करें

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

ज़्यादा जानकारी के लिए, बहुत ज़्यादा स्किप करना लेख पढ़ें.

क्लास को नहीं बदले जा सकने वाला बनाएं

आप एक अस्थिर क्लास को पूरी तरह से नहीं बदले जाने लायक बनाने की कोशिश भी कर सकते हैं.

  • अम्यूटेबल: इससे पता चलता है कि किसी भी प्रॉपर्टी की वैल्यू कभी भी नहीं हो सकती उस तरह का कोई इंस्टेंस बनने के बाद बदल जाता है और सभी तरीके साफ़ तौर पर बताया जाता है.
    • पक्का करें कि सभी क्लास की प्रॉपर्टी, var के बजाय val हों. और नहीं बदले जा सकने वाले हैं.
    • String, Int और Float जैसे प्रिमिटिव टाइप हमेशा नहीं बदले जा सकते.
    • अगर ऐसा नहीं किया जा सकता, तो आपको बदली जा सकने वाली प्रॉपर्टी.
  • स्टेबल: यह ऐसे टाइप के बारे में बताता है जिसमें बदलाव किया जा सकता है. लिखने का रनटाइम ये काम नहीं करता है ध्यान दें, अगर और जब किसी भी टाइप की सार्वजनिक प्रॉपर्टी या तरीका इस तरह के व्यवहार के नतीजे, पिछली बार शुरू करने से अलग होंगे.

नहीं बदले जा सकने वाले कलेक्शन

Compose में क्लास को हिलने-डुलने की एक आम वजह, कलेक्शन है. जैसा कि नोट किया गया है स्थिरता से जुड़ी समस्याओं का पता लगाएं पेज पर, Compose कंपाइलर नहीं हो सकता कि List, Map और Set जैसे संग्रह जो पूरी तरह से नहीं बदले जा सकते. इस वजह से, इन्हें स्टेबल के तौर पर मार्क किया जाता है.

इसे ठीक करने के लिए, ऐसे कलेक्शन इस्तेमाल किए जा सकते हैं जिन्हें बदला नहीं जा सकता. द कंपोज़ कंपाइलर इसमें Kotlinx के इम्यूटेबल कलेक्शन के लिए सहायता शामिल है. ये इस बात की गारंटी है कि कलेक्शन में कोई बदलाव नहीं किया जा सकता. साथ ही, कंपोज़ कंपाइलर उन्हें ट्रैक किया जा सकता है. यह लाइब्रेरी अब भी ऐल्फ़ा वर्शन में है, इसलिए इसके एपीआई में बदलाव हो सकते हैं.

स्थिरता का विश्लेषण करें समस्याएं गाइड:

unstable class Snack {
  …
  unstable val tags: Set<String>
  …
}

ऐसे कलेक्शन का इस्तेमाल करके tags को स्थिर बनाया जा सकता है जिसे बदला नहीं जा सकता. क्लास में, बदलें tags से ImmutableSet<String> तक का टाइप:

data class Snack{
    …
    val tags: ImmutableSet<String> = persistentSetOf()
    …
}

ऐसा करने के बाद, क्लास के सभी पैरामीटर में बदलाव नहीं किया जा सकता और Compose में बदलाव नहीं किया जा सकता कंपाइलर, क्लास को स्टेबल के तौर पर मार्क करता है.

Stable या Immutable के साथ एनोटेट करें

स्थिरता से जुड़ी समस्याओं को हल करने का एक संभावित तरीका है, अस्थिर क्लास की व्याख्या करना @Stable या @Immutable के साथ.

क्लास की व्याख्या करने से यह बदल जाता है कि कंपाइलर क्या करता है अपनी क्लास के बारे में अनुमान लगाएं. यह !! Kotlin की मदद से ऑपरेटर. आपको ऐसा होना चाहिए ध्यान दें कि आप इन एनोटेशन का इस्तेमाल कैसे करते हैं. कंपाइलर के व्यवहार में बदलाव करना इससे आपके कॉन्टेंट में अचानक होने वाली गड़बड़ियां पैदा हो सकती हैं. जैसे आप ऐसा करने की उम्मीद करते हैं.

अगर किसी एनोटेशन के बिना आपकी क्लास को स्थिर बनाया जा सकता है, तो आपको ताकि स्थिरता लाने की कोशिश की जाए.

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

@Immutable
data class Snack(
…
)

चाहे आप @Immutable एनोटेशन का इस्तेमाल करें या @Stable एनोटेशन का, Compose कंपाइलर Snack क्लास को स्टेबल के तौर पर मार्क करता है.

कलेक्शन में एनोटेट की गई क्लास

कोई ऐसा कंपोज़ेबल चुनें जिसमें List<Snack> टाइप का पैरामीटर शामिल हो:

restartable scheme("[androidx.compose.ui.UiComposable]") fun HighlightedSnacks(
  …
  unstable snacks: List<Snack>
  …
)

भले ही, Snack के बारे में @Immutable के साथ एनोटेट किया जाए, लेकिन कंपोज़ कंपाइलर अब भी HighlightedSnacks में मौजूद snacks पैरामीटर को ठीक से सेट नहीं किया गया है.

जब बात कलेक्शन टाइप की आती है, तब पैरामीटर को क्लास वाली समस्या का सामना करना पड़ता है, Compose कंपाइलर हमेशा List टाइप के पैरामीटर को 'अस्तबल' के तौर पर मार्क करता है, यहां तक कि जब यह स्थायी प्रकारों का संग्रह हो.

किसी एक पैरामीटर को न तो स्थिर के तौर पर मार्क किया जा सकता है और न ही किसी पैरामीटर को बनाया जा सके, जिसे हमेशा स्किप किया जा सके. आगे कई रास्ते हैं.

कलेक्शन में बदलाव न होने से जुड़ी समस्या को हल करने के कई तरीके हैं. इन सब-सेक्शन में, इन अलग-अलग तरीकों के बारे में बताया गया है.

कॉन्फ़िगरेशन फ़ाइल

अगर आपको अपने कोड बेस में स्थिरता से जुड़े अनुबंध का पालन करना है, तो आपके पास यह विकल्प है कि आप Kotlin कलेक्शन को स्टेबल मान सकें. इसके लिए, kotlin.collections.* को आपके स्टेबिलिटी कॉन्फ़िगरेशन फ़ाइल.

इम्यूटेबल कलेक्शन

नहीं बदले जा सकने वाले टाइम की सुरक्षा को कंपाइल करने के लिए, आपके पास List के बजाय, kotlinx के नहीं बदले जा सकने वाले कलेक्शन का इस्तेमाल करें.

@Composable
private fun HighlightedSnacks(
    …
    snacks: ImmutableList<Snack>,
    …
)

Wrapper

अगर ऐसे कलेक्शन का इस्तेमाल नहीं किया जा सकता जिसमें बदलाव नहीं किया जा सकता, तो अपना कलेक्शन बनाया जा सकता है. ऐसा करने के लिए, List को एनोटेट की गई स्टेबल क्लास में रैप करें. आम तौर पर, एक जेनरिक रैपर इसके लिए सबसे अच्छा विकल्प चुनें.

@Immutable
data class SnackCollection(
   val snacks: List<Snack>
)

इसके बाद, इसे अपने कंपोज़ेबल में पैरामीटर के टाइप के तौर पर इस्तेमाल किया जा सकता है.

@Composable
private fun HighlightedSnacks(
    index: Int,
    snacks: SnackCollection,
    onSnackClick: (Long) -> Unit,
    modifier: Modifier = Modifier
)

समाधान

इनमें से कोई भी तरीका अपनाने के बाद, Compose कंपाइलर अब HighlightedSnacks skippable और restartable, दोनों में कंपोज़ेबल.

restartable skippable scheme("[androidx.compose.ui.UiComposable]") fun HighlightedSnacks(
  stable index: Int
  stable snacks: ImmutableList<Snack>
  stable onSnackClick: Function1<Long, Unit>
  stable modifier: Modifier? = @static Companion
)

बदलाव के दौरान, अगर इनमें से कोई भी विकल्प नहीं चुना गया है, तो कंपोज़ की सुविधा अब HighlightedSnacks को स्किप कर सकती है इनपुट बदल गए हैं.

स्थिरता से जुड़ी कॉन्फ़िगरेशन फ़ाइल

कंपोज़ कंपाइलर 1.5.5 से शुरू करना, जो कंपाइल करने के दौरान, स्टेबल वैल्यू दी जा सकती है. इससे हमें यह समझने में मदद मिलती है कि ऐसी क्लास जिन्हें कंट्रोल नहीं किया जाता है, जैसे कि स्टैंडर्ड लाइब्रेरी क्लास LocalDateTime जैसा, स्थिर.

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

// Consider LocalDateTime stable
java.time.LocalDateTime
// Consider kotlin collections stable
kotlin.collections.*
// Consider my datalayer and all submodules stable
com.datalayer.**
// Consider my generic type stable based off it's first type parameter only
com.example.GenericClass<*,_>

इस सुविधा को चालू करने के लिए, कॉन्फ़िगरेशन फ़ाइल के पाथ को Compose में भेजें कंपाइलर विकल्प.

ग्रूवी

kotlinOptions {
    freeCompilerArgs += [
            "-P",
            "plugin:androidx.compose.compiler.plugins.kotlin:stabilityConfigurationPath=" +
                    project.absolutePath + "/compose_compiler_config.conf"
    ]
}

Kotlin

kotlinOptions {
  freeCompilerArgs += listOf(
      "-P",
      "plugin:androidx.compose.compiler.plugins.kotlin:stabilityConfigurationPath=" +
      "${project.absolutePath}/compose_compiler_config.conf"
  )
}

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

एक से ज़्यादा मॉड्यूल

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

अगर आपकी डेटा लेयर, आपकी यूज़र इंटरफ़ेस (यूआई) लेयर के किसी अलग मॉड्यूल में है, जो सुझाया गया तरीका इस्तेमाल किया है, तो इस समस्या का सामना करना पड़ सकता है.

समाधान

इस समस्या को हल करने के लिए, इनमें से कोई एक तरीका आज़माया जा सकता है:

  1. क्लास को अपनी कंपाइलर कॉन्फ़िगरेशन फ़ाइल में जोड़ें.
  2. अपने डेटा लेयर मॉड्यूल पर, Compose कंपाइलर चालू करें या अपनी क्लास को टैग करें @Stable या @Immutable के साथ.
    • इसमें, आपके डेटा लेयर में Compose डिपेंडेंसी जोड़ना शामिल है. हालांकि, यह सिर्फ़ Compose के रनटाइम पर निर्भर करता है, न कि Compose-UI.
  3. अपने यूज़र इंटरफ़ेस (यूआई) मॉड्यूल में, अपने डेटा लेयर की क्लास को यूज़र इंटरफ़ेस (यूआई) के हिसाब से रैपर में रैप करें क्लास.

बाहरी लाइब्रेरी का इस्तेमाल करते समय भी यही समस्या आती है. ऐसा तब होता है, जब वे कंपाइलर लिखें.

सभी कंपोज़ेबल को स्किप नहीं किया जाना चाहिए

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

ऐसी कई स्थितियां हैं जिनमें स्किप किए जा सकने वाले वीडियो का कोई खास फ़ायदा नहीं होता और इससे कोड का रखरखाव करना मुश्किल हो सकता है. उदाहरण के लिए:

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

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