Compose में स्टैक ट्रेस

Jetpack Compose आपके कोड को कई अलग-अलग फ़ेज़ में लागू करता है. इस वजह से, @Composable फ़ंक्शन के कुछ हिस्से एक-दूसरे से अलग लागू होते हैं. इन चरणों में होने वाले क्रैश की वजह से, स्टैक ट्रेस को समझना मुश्किल हो सकता है. इससे, क्रैश की वजह बनने वाले फ़ंक्शन या कोड की लाइन का पता लगाना मुश्किल हो जाता है.

स्टैक ट्रेस में सोर्स की जानकारी जोड़ना

स्टैक ट्रेस को आसानी से पढ़ने के लिए, ऑप्ट-इन एपीआई, क्रैश की जगह की ज़्यादा जानकारी देता है. इसमें कंपोज़ेबल के नाम और जगहें शामिल होती हैं. इससे आपको ये काम करने में मदद मिलती है:

  • क्रैश की वजहों का आसानी से पता लगाएं और उन्हें ठीक करें
  • क्रैश की समस्या को फिर से पैदा करने वाले सैंपल को अलग करना
  • उन क्रैश की जांच करना जिनमें पहले सिर्फ़ इंटरनल स्टैक फ़्रेम दिखते थे

Compose रनटाइम, कंपोज़िशन में क्रैश की जगह का पता लगा सकता है. साथ ही, आपकी @Composable हैरारकी के आधार पर स्टैक ट्रेस को फिर से बना सकता है. स्टैक ट्रेस को इनमें होने वाले क्रैश के लिए जोड़ा जाता है:

  • कंपोज़िशन
  • DisposableEffect और LaunchedEffect (onDispose या सदस्यता रद्द करने के अलावा)
  • rememberCoroutineScope में लॉन्च किए गए कोरूटीन
  • मेज़रमेंट, लेआउट, और ड्रॉइंग पास

इस सुविधा को चालू करने के लिए, ऐप्लिकेशन के एंट्री पॉइंट में ये लाइनें जोड़ें:

// Enable stack traces at application level: onCreate
class SampleStackTracesEnabledApp : Application() {

    override fun onCreate() {
        super.onCreate()
        // Enable Compose stack traces for minified builds only.
        Composer.setDiagnosticStackTraceMode(ComposeStackTraceMode.Auto)

        // Alternatively:
        // Enable verbose Compose stack traces for local debugging
        Composer.setDiagnosticStackTraceMode(ComposeStackTraceMode.SourceInformation)
    }
}

हमारा सुझाव है कि कोई भी कंपोज़िशन बनाने से पहले, यह कॉन्फ़िगरेशन करें. इससे यह पुष्टि की जा सकेगी कि स्टैक ट्रेस की जानकारी सही तरीके से इकट्ठा की गई है.

ComposeStackTraceMode के लिए चार विकल्प हैं:

  • Auto: यह विकल्प इस्तेमाल करने का सुझाव दिया जाता है, क्योंकि अगर ऐप्लिकेशन को छोटा किया गया है, तो यह GroupKeys का इस्तेमाल करता है. अगर ऐसा नहीं है, तो यह None का इस्तेमाल करता है.
  • GroupKeys: स्टैक ट्रेस, काट-छांट किए गए ऐप्लिकेशन के लिए बनाए जाते हैं. ग्रुप की मुख्य जानकारी, काट-छांट के बाद भी सेव रहती है. इसका इस्तेमाल, Compose कंपाइलर और R8 से जनरेट की गई ProGuard मैपिंग फ़ाइल के साथ किया जाता है, ताकि @Composable फ़ंक्शन की जगह की अनुमानित जानकारी फिर से बनाई जा सके. ये स्टैक ट्रेस कम सटीक होते हैं. इन्हें इस तरह ऑप्टिमाइज़ किया जाता है कि रनटाइम के दौरान ज़्यादा काम न करना पड़े. Compose कंपाइलर, Kotlin 2.3.0 और इसके बाद के वर्शन से, अतिरिक्त R8 मैपिंग को जनरेट करने की सुविधा देता है.
  • SourceInformation: यह उन बिल्ड के लिए काम का है जिनकी काट-छांट नहीं की गई है. यह सोर्स की जानकारी इकट्ठा करता है और उसे स्टैक ट्रेस में जोड़ता है. इससे मिलने वाले नतीजे ज़्यादा सटीक होते हैं. हालांकि, इससे परफ़ॉर्मेंस पर काफ़ी असर पड़ता है. यह असर, लेआउट इंस्पेक्टर को अटैच करने जैसा ही होता है. इन्हें ऐप्लिकेशन के डीबग वर्शन में इस्तेमाल करने के लिए बनाया जाता है, ताकि क्रैश के बारे में सटीक जानकारी मिल सके. इसके लिए, क्रैश की जगह के बारे में ज़्यादा जानकारी की ज़रूरत होती है. बाइनरी साइज़ और परफ़ॉर्मेंस को ऑप्टिमाइज़ करने के लिए, सोर्स की जानकारी को छोटे किए गए ऐप्लिकेशन से हटा दिया जाता है.
  • None: स्टैक ट्रेस की कोई अतिरिक्त जानकारी नहीं जोड़ी गई.

SourceInformation विकल्प का इस्तेमाल करने पर, स्टैक ट्रेस, दबाए गए अपवाद की सूची में DiagnosticComposeException के तौर पर दिखता है:

java.lang.IllegalStateException: Test layout error
    at <original trace>
Suppressed: androidx.compose.runtime.DiagnosticComposeException:
Composition stack when thrown:
    at ReusableComposeNode(Composables.kt:<unknown line>)
    at Layout(Layout.kt:79)
    at <lambda>(TempErrorsTest.kt:164)
    at <lambda>(BoxWithConstraints.kt:66)
    at ReusableContentHost(Composables.kt:164)
    at <lambda>(SubcomposeLayout.kt:514)
    at SubcomposeLayout(SubcomposeLayout.kt:114)
    at SubcomposeLayout(SubcomposeLayout.kt:80)
    at BoxWithConstraints(BoxWithConstraints.kt:64)
    at SubcomposeLayoutErrorComposable(TempErrorsTest.kt:164)
    at <lambda>(TempErrorsTest.kt:86)
    at Content(ComposeView.android.kt:430)
    at <lambda>(ComposeView.android.kt:249)
    at CompositionLocalProvider(CompositionLocal.kt:364)
    at ProvideCommonCompositionLocals(CompositionLocals.kt:193)
    at <lambda>(AndroidCompositionLocals.android.kt:113)
    at CompositionLocalProvider(CompositionLocal.kt:364)
    at ProvideAndroidCompositionLocals(AndroidCompositionLocals.android.kt:102)
    at <lambda>(Wrapper.android.kt:141)
    at CompositionLocalProvider(CompositionLocal.kt:384)
    at <lambda>(Wrapper.android.kt:140)

सीमाएं

स्टैक ट्रेस फ़्रेम से जुड़ी कुछ समस्याएं हैं:

सोर्स की जानकारी के स्टैक ट्रेस

कंपोज़िशन में क्रैश होने की वजह से, पहले स्टैक फ़्रेम में लाइन नंबर (<unknown line>) मौजूद नहीं हैं. सोर्स की जानकारी की जांच, क्रैश होने के बाद की जा रही है. इसलिए, हो सकता है कि स्लॉट टेबल का डेटा अधूरा हो और लाइन नंबर न दिखे. ReusableComposeNode और remember सोर्स की जानकारी नहीं देते हैं. इसलिए, आपको उन फ़ंक्शन के स्टैक फ़्रेम में <unknown line> दिखेगा.

ग्रुप कीज़ स्टैक ट्रेस

GroupKeys पर आधारित स्टैक ट्रेस, डिज़ाइन के हिसाब से सिर्फ़ @Composable फ़ंक्शन की पहली लाइन पर ले जा सकते हैं. इनमें ऐसे फ़ंक्शन का डेटा भी शामिल नहीं होता जो कोई ग्रुप नहीं बनाते. जैसे, इनलाइन या नॉन-यूनिट रिटर्न करने वाले फ़ंक्शन

स्टैक ट्रेस कलेक्शन क्रैश

अगर स्टैक ट्रेस कलेक्शन किसी वजह से क्रैश हो जाता है, तो उस अपवाद को DiagnosticComposeException के बजाय, दबाए गए अपवाद के तौर पर जोड़ा जाता है.

दबाए गए किसी भी क्रैश या स्टैक ट्रेस की गड़बड़ियों की शिकायत, Compose रनटाइम कॉम्पोनेंट को करें.