Jetpack Compose 会在多个不同阶段执行您的代码,这会导致 @Composable 函数的某些部分彼此分开执行。这些阶段发生的崩溃可能会导致堆栈轨迹难以解读,从而难以确定导致崩溃的确切函数或代码行。
向堆栈轨迹添加源代码信息
为了提高堆栈轨迹的可读性,我们提供了一个选择启用的 API,该 API 可提供更丰富的崩溃位置详细信息,包括可组合项名称和位置,使您能够:
- 高效识别和解决崩溃来源
- 隔离崩溃以获取可重现的示例
- 调查之前仅显示内部堆栈帧的崩溃
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函数的大致位置。 这些堆栈轨迹不太精确,经过优化,可避免在运行时执行额外的工作。从 Kotlin 2.3.0 开始,Compose 编译器支持发出额外的 R8 映射。SourceInformation:适用于未缩减大小的 build,可收集源代码信息并将其添加到堆栈轨迹中。结果更准确,但会产生与附加布局检查器类似的显著性能开销。它们旨在用于应用的调试版本,以便准确读取需要更多位置信息的崩溃。系统会从缩减大小的应用中移除源代码信息,以优化二进制文件大小和性能。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 运行时组件报告任何被抑制的崩溃或堆栈轨迹不一致问题。