Dấu vết ngăn xếp trong Compose

Jetpack Compose thực thi mã của bạn theo nhiều giai đoạn, khiến một số phần của hàm @Composable được thực thi riêng biệt với nhau. Sự cố trong các giai đoạn này có thể dẫn đến dấu vết ngăn xếp khó giải mã, khiến bạn khó xác định chính xác hàm hoặc dòng mã gây ra sự cố.

Thêm thông tin nguồn vào dấu vết ngăn xếp

Để cải thiện khả năng đọc dấu vết ngăn xếp, một API chọn tham gia sẽ cung cấp thông tin chi tiết hơn về vị trí xảy ra sự cố, bao gồm cả tên và vị trí của composable, cho phép bạn:

  • Xác định và giải quyết hiệu quả các nguồn gây sự cố
  • Tách biệt sự cố để lấy mẫu có thể tái hiện
  • Điều tra các sự cố mà trước đây chỉ cho thấy khung ngăn xếp nội bộ

Thời gian chạy Compose có thể phát hiện vị trí xảy ra sự cố trong thành phần và tạo lại dấu vết ngăn xếp dựa trên hệ phân cấp @Composable của bạn. Dấu vết ngăn xếp được thêm vào cho các sự cố trong:

  • Bản sáng tác
  • DisposableEffect và LaunchedEffect (ngoại trừ onDispose hoặc huỷ)
  • Coroutine được khởi chạy trong rememberCoroutineScope
  • Lượt đo lường, bố cục và vẽ

Để bật tính năng này, hãy thêm các dòng sau vào điểm truy cập của ứng dụng:

// 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)
    }
}

Tốt nhất là bạn nên thực hiện cấu hình này trước khi tạo bất kỳ thành phần kết hợp nào để xác minh rằng thông tin dấu vết ngăn xếp được thu thập chính xác.

Có 4 lựa chọn cho ComposeStackTraceMode:

  • Auto: Lựa chọn nên dùng vì lựa chọn này sử dụng GroupKeys nếu ứng dụng được rút gọn và None nếu không.
  • GroupKeys: Dấu vết ngăn xếp được tạo cho các ứng dụng đã rút gọn. Thông tin khoá nhóm được giữ lại ngay cả sau khi rút gọn và được dùng cùng với tệp ánh xạ proguard do trình biên dịch Compose và R8 phát ra để tái cấu trúc vị trí thô của các hàm @Composable. Những dấu vết ngăn xếp này ít chính xác hơn và được tối ưu hoá để tránh thực hiện thêm công việc trong thời gian chạy. Trình biên dịch Compose hỗ trợ phát hành thêm các tệp ánh xạ R8 kể từ Kotlin 2.3.0.
  • SourceInformation: Hữu ích cho các bản dựng không được rút gọn, thu thập thông tin nguồn và thêm thông tin đó vào dấu vết ngăn xếp. Kết quả sẽ chính xác hơn, nhưng tốn nhiều hiệu suất, tương tự như việc đính kèm Layout Inspector. Các tệp này được tạo để sử dụng trong các phiên bản gỡ lỗi của ứng dụng nhằm nhận được thông tin chính xác về sự cố cần thêm thông tin về vị trí của sự cố. Thông tin nguồn sẽ bị xoá khỏi các ứng dụng đã rút gọn để tối ưu hoá kích thước và hiệu suất tệp nhị phân.
  • None: Không thêm thông tin chi tiết về dấu vết ngăn xếp bổ sung.

Khi sử dụng tuỳ chọn SourceInformation, dấu vết ngăn xếp sẽ xuất hiện dưới dạng DiagnosticComposeException trong danh sách ngoại lệ bị chặn:

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)

Các hạn chế đã biết

Có một số vấn đề đã biết về khung dấu vết ngăn xếp:

Dấu vết ngăn xếp thông tin nguồn

Thiếu số dòng (<unknown line>) trong khung ngăn xếp đầu tiên cho các sự cố trong thành phần. Vì quá trình xem xét thông tin nguồn diễn ra sau sự cố, nên dữ liệu bảng vị trí có thể không đầy đủ và bị mất số dòng. ReusableComposeNode và remember không tạo ra thông tin nguồn, vì vậy, bạn sẽ thấy <unknown line> trong khung ngăn xếp cho các hàm đó.

Dấu vết ngăn xếp khoá nhóm

Dấu vết ngăn xếp dựa trên GroupKeys chỉ có thể trỏ đến dòng đầu tiên của hàm @Composable theo thiết kế. Các hàm này cũng không chứa dữ liệu cho bất kỳ hàm nào không tạo ra nhóm (chẳng hạn như hàm cùng dòng hoặc hàm không trả về Unit)

Sự cố khi thu thập dấu vết ngăn xếp

Nếu tập hợp dấu vết ngăn xếp gặp sự cố vì bất kỳ lý do gì, thì ngoại lệ đó sẽ được thêm vào dưới dạng ngoại lệ bị chặn thay vì DiagnosticComposeException.

Báo cáo mọi sự cố bị chặn hoặc sự không nhất quán về dấu vết ngăn xếp cho thành phần Thời gian chạy của Compose.