Jetpack Compose 会在多个不同的阶段执行代码,这会导致 @Composable 函数的某些部分彼此分开执行。在这些阶段发生的崩溃可能会导致难以解读的堆栈轨迹,从而难以精确定位导致崩溃的确切函数或代码行。
向堆栈轨迹添加源代码信息
为了提高堆栈轨迹的可读性,选择启用的 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>)。由于源信息自省是在崩溃后发生的,因此 slot 表数据可能不完整,并且会丢弃行号。ReusableComposeNode 和 remember 不会生成源代码信息,因此您会在这些函数的堆栈帧中看到 <unknown line>。
组密钥堆栈轨迹
根据设计,基于 GroupKeys 的堆栈轨迹只能指向 @Composable 函数的第一行。它们也不包含任何不生成组的函数(例如内联函数或不返回 Unit 的函数)的数据
堆栈轨迹收集崩溃
如果堆栈轨迹收集因任何原因而崩溃,则该异常会附加为抑制异常,而不是 DiagnosticComposeException。
向 Compose 运行时组件报告任何被抑制的崩溃或堆栈轨迹不一致问题。