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

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

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

Для повышения читаемости трассировки стека доступен API с возможностью выбора, предоставляющий более подробную информацию о местах сбоев, включая составные имена и местоположения, что позволяет:

  • Эффективно выявлять и устранять причины сбоев.
  • Выделение сбоев для воспроизводимых образцов.
  • Расследуйте сбои, которые ранее отображали только внутренние кадры стека.

Среда выполнения Compose может определить место сбоя в композиции и восстановить трассировку стека на основе вашей иерархии @Composable . Трассировка стека добавляется для сбоев в следующих местах:

  • Композиция
  • DisposableEffect и LaunchedEffect (за исключением onDispose или cancellation)
  • Сопрограммы, запущенные в 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 Runtime .