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 には 4 つのオプションがあります。
Auto: 推奨オプション。アプリが圧縮されている場合はGroupKeysを使用し、それ以外の場合はNoneを使用します。GroupKeys: 縮小されたアプリのスタック トレースが作成されます。グループキー情報は、圧縮後も保持され、Compose コンパイラと R8 によって出力された ProGuard マッピング ファイルとともに使用され、@Composable関数の大まかな位置を再構築します。これらのスタック トレースは精度が低く、実行時に追加の作業を行わないように最適化されています。Compose コンパイラは、Kotlin 2.3.0 以降で追加の R8 マッピングの出力をサポートしています。SourceInformation: 縮小されていないビルドに便利です。ソース情報を収集してスタック トレースに追加します。結果はより正確になりますが、Layout Inspector をアタッチする場合と同様に、パフォーマンス コストが大幅に増加します。これらは、アプリのデバッグ バージョンで使用するために作成され、クラッシュの場所に関する詳細情報を必要とするクラッシュを正確に読み取ることができます。バイナリサイズとパフォーマンスを最適化するために、ソース情報は難読化されたアプリから削除されます。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 ランタイム コンポーネントに報告します。