Трассировки стека в Compose

Jetpack Compose выполняет ваш код в несколько разных этапов, в результате чего некоторые части функции @Composable выполняются отдельно друг от друга. Сбои на этих этапах могут привести к трассировке стека, которую трудно расшифровать, что затрудняет точное определение функции или строки кода, вызвавшей сбой.

Добавление информации об источнике в трассировки стека

Чтобы трассировку стека было проще читать, мы добавили API, который предоставляет более подробные сведения о месте сбоя, включая названия и местоположения 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: трассировки стека создаются для минифицированных приложений. Информация о ключе группы сохраняется даже после минификации и используется вместе с файлом сопоставления ProGuard, созданным компилятором Compose и R8, чтобы восстановить приблизительное местоположение функций @Composable. Эти трассировки стека менее точны и оптимизированы так, чтобы не выполнять дополнительную работу во время выполнения. Компилятор Compose поддерживает создание дополнительных сопоставлений R8, начиная с Kotlin 2.3.0.
  • 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. Они также не содержат данных для функций, которые не создают группу (например, встроенных функций или функций, не возвращающих Unit).

Сбои при сборе трассировки стека

Если сбор трассировки стека по какой-либо причине завершается сбоем, это исключение добавляется как подавленное вместо DiagnosticComposeException.

Сообщайте о любых скрытых сбоях или несоответствиях трассировки стека в компонент среды выполнения Compose.