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

कंपाइलर रिपोर्ट तैयार करना
Compose कंपाइलर, जांच के लिए स्टेबिलिटी के अनुमान के नतीजे दिखा सकता है. इस आउटपुट का इस्तेमाल करके, यह तय किया जा सकता है कि आपके कौनसे कंपोज़ेबल स्किप किए जा सकते हैं और कौनसे नहीं. यहां दिए गए सब-सेक्शन में, इन रिपोर्ट को इस्तेमाल करने के तरीके के बारे में खास जानकारी दी गई है. हालांकि, ज़्यादा जानकारी के लिए तकनीकी दस्तावेज़ देखें.
सेटअप
Compose कंपाइलर रिपोर्ट, डिफ़ॉल्ट रूप से चालू नहीं होती हैं. इन्हें कंपाइलर फ़्लैग की मदद से चालू किया जा सकता है. सेटअप आपके प्रोजेक्ट के हिसाब से अलग-अलग होता है. हालांकि, Compose कंपाइलर Gradle प्लग इन का इस्तेमाल करने वाले प्रोजेक्ट के लिए, हर मॉड्यूल की build.gradle फ़ाइल में यह कोड जोड़ा जा सकता है.
android { ... }
composeCompiler {
reportsDestination = layout.buildDirectory.dir("compose_compiler")
metricsDestination = layout.buildDirectory.dir("compose_compiler")
}
अब आपका प्रोजेक्ट बनाते समय, Compose कंपाइलर की रिपोर्ट जनरेट होंगी.
आउटपुट का उदाहरण
reportsDestination से तीन फ़ाइलें आउटपुट के तौर पर मिलती हैं. JetSnack के आउटपुट के उदाहरण यहां दिए गए हैं.
<modulename>-classes.txt: इस मॉड्यूल में क्लास की स्थिरता के बारे में रिपोर्ट. सैंपल.<modulename>-composables.txt: इस रिपोर्ट से पता चलता है कि मॉड्यूल में मौजूद कंपोज़ेबल, फिर से शुरू किए जा सकते हैं और स्किप किए जा सकते हैं या नहीं. सैंपल.<modulename>-composables.csv:कंपोज़ेबल रिपोर्ट काCSVवर्शन, जिसे स्प्रेडशीट में इंपोर्ट किया जा सकता है या स्क्रिप्ट का इस्तेमाल करके प्रोसेस किया जा सकता है. सैंपल
कंपोज़ेबल रिपोर्ट
composables.txt फ़ाइल में, दिए गए मॉड्यूल के लिए ऐप्लिकेशन बनाने की सुविधा देने वाले हर फ़ंक्शन की जानकारी होती है. इसमें उनके पैरामीटर की स्टेबिलिटी के साथ-साथ, यह जानकारी भी शामिल होती है कि उन्हें रीस्टार्ट किया जा सकता है या स्किप किया जा सकता है. यहां JetSnack का एक उदाहरण दिया गया है:
restartable skippable scheme("[androidx.compose.ui.UiComposable]") fun SnackCollection(
stable snackCollection: SnackCollection
stable onSnackClick: Function1<Long, Unit>
stable modifier: Modifier? = @static Companion
stable index: Int = @static 0
stable highlight: Boolean = @static true
)
इस उदाहरण में, SnackCollection के हर पैरामीटर को stable के तौर पर मार्क किया गया है. इसलिए, Compose हर पैरामीटर की तुलना स्ट्रक्चरल समानता (Object.equals()) का इस्तेमाल करके करता है. stable पैरामीटर, प्रिमिटिव वैल्यू और छोटे, फ़्लैट डेटा क्लास के लिए सबसे सही होते हैं. इनमें .equals() की जांच करना आसान होता है. हालांकि, कलेक्शन होल्डिंग मॉडल (जैसे, List<Snack> को रैप करने वाला SnackCollection) को stable होने के लिए मजबूर करने पर, Compose हर बार फिर से कॉम्पोज़ करने पर हर आइटम पर .equals() को कॉल करता है. स्ट्रॉन्ग स्किपिंग मोड चालू होने पर, हमारा सुझाव है कि आप कलेक्शन unstable को होल्ड करने वाले मॉडल रखें, ताकि Compose उनकी तुलना करने के लिए, इंस्टेंस की समानता (===) का इस्तेमाल कर सके.
इसके अलावा, स्ट्रॉन्ग स्किपिंग मोड बंद करके जनरेट किए गए इस उदाहरण को देखें:
restartable scheme("[androidx.compose.ui.UiComposable]") fun HighlightedSnacks(
stable index: Int
unstable snacks: List<Snack>
stable onSnackClick: Function1<Long, Unit>
stable modifier: Modifier? = @static Companion
)
जब स्ट्रॉन्ग स्किपिंग मोड बंद होता है (Kotlin 2.0.20 से पहले), तो HighlightedSnacks कंपोज़ेबल को स्किप नहीं किया जा सकता. Compose, रीकंपोज़िशन के दौरान इसे कभी स्किप नहीं करता. भले ही, इसका कोई भी पैरामीटर न बदला हो. ऐसा unstable पैरामीटर snacks की वजह से होता है.
स्ट्रॉन्ग स्किपिंग मोड चालू होने पर (Kotlin 2.0.20 और इसके बाद के वर्शन में डिफ़ॉल्ट रूप से चालू होता है), HighlightedSnacks को skippable के तौर पर मार्क किया जाता है. साथ ही, Compose, इंस्टेंस की समानता (===) का इस्तेमाल करके, unstable पैरामीटर snacks की तुलना करता है. इस वजह से, अगर एक ही List रेफ़रंस पास किया जाता है, तो Compose, HighlightedSnacks को स्किप कर देता है. साथ ही, नया List इंस्टेंस पास किए जाने पर ही, उसे फिर से कंपोज़ करता है.
क्लास की रिपोर्ट
classes.txt फ़ाइल में, दिए गए मॉड्यूल की क्लास के बारे में मिलती-जुलती रिपोर्ट है. यहां दिया गया स्निपेट, Snack क्लास का आउटपुट है:
unstable class Snack {
stable val id: Long
stable val name: String
stable val imageUrl: String
stable val price: Long
stable val tagline: String
unstable val tags: Set<String>
<runtime stability> = Unstable
}
आपकी जानकारी के लिए, Snack की परिभाषा यहां दी गई है:
data class Snack(
val id: Long,
val name: String,
val imageUrl: String,
val price: Long,
val tagline: String = "",
val tags: Set<String> = emptySet()
)
Compose कंपाइलर ने Snack को अनस्टेबल के तौर पर मार्क किया है. ऐसा इसलिए है, क्योंकि tags पैरामीटर का टाइप Set<String> है. यह एक इम्यूटेबल टाइप है, क्योंकि यह MutableSet नहीं है. हालांकि, Set, List, और Map जैसी स्टैंडर्ड कलेक्शन क्लास, इंटरफ़ेस होती हैं. इसलिए, हो सकता है कि लागू किए गए
अंडरलाइंग कोड में अब भी बदलाव किया जा सके.
उदाहरण के लिए, val set: Set<String> = mutableSetOf("foo") लिखा जा सकता है. वैरिएबल कॉन्स्टेंट है और इसका एलान किया गया टाइप बदला नहीं जा सकता. हालांकि, इसे लागू करने का तरीका अब भी बदला जा सकता है. Compose कंपाइलर, इस क्लास के इम्यूटेबल होने की पुष्टि नहीं कर सकता, क्योंकि यह सिर्फ़ तय किए गए टाइप को देखता है. इसलिए, यह tags को अस्थिर के तौर पर मार्क करता है.