Nếu đang gặp vấn đề về hiệu suất do việc kết hợp lại quá mức hoặc không cần thiết, bạn nên gỡ lỗi để ổn định ứng dụng của mình. Hướng dẫn này đề ra một số phương pháp để thực hiện điều này.
Layout Inspector
Layout Inspector trong Android Studio cho phép bạn xem thành phần kết hợp nào đang được kết hợp lại trong ứng dụng của mình. Công cụ này cũng cho thấy số lần Compose đã kết hợp lại hoặc bỏ qua một thành phần.

Báo cáo của trình biên dịch Compose
Trình biên dịch Compose có thể đưa ra kết quả suy luận về độ ổn định của nó để bạn kiểm tra. Bằng cách sử dụng kết quả này, bạn có thể xác định thành phần kết hợp nào có thể bỏ qua và thành phần nào thì không. Các tiểu mục tiếp theo tóm tắt cách sử dụng các báo cáo này, nhưng để biết thêm thông tin, hãy xem tài liệu kỹ thuật.
Thiết lập
Tính năng báo cáo của trình biên dịch Compose không được bật theo mặc định. Bạn có thể bật tính năng này bằng cờ của trình biên dịch. Các bước thiết lập chính xác còn tuỳ thuộc vào dự án của bạn. Nhưng đối với các dự án sử dụng trình bổ trợ Gradle của trình biên dịch Compose, bạn có thể thêm đoạn mã sau vào tệp build.gradle của từng mô-đun.
android { ... }
composeCompiler {
reportsDestination = layout.buildDirectory.dir("compose_compiler")
metricsDestination = layout.buildDirectory.dir("compose_compiler")
}
Giờ đây, báo cáo của trình biên dịch Compose sẽ được tạo khi bạn xây dựng dự án.
Kết quả ví dụ
reportsDestination xuất ra 3 tệp. Sau đây là các ví dụ kết quả đầu ra từ JetSnack.
<modulename>-classes.txt: Một báo cáo về tính ổn định của các lớp trong mô-đun này. Mẫu.<modulename>-composables.txt: Một báo cáo về khả năng khởi động lại và bỏ qua của các thành phần kết hợp trong mô-đun. Mẫu.<modulename>-composables.csv: Một phiên bảnCSVcủa báo cáo về thành phần kết hợp. Bạn có thể nhập báo cáo này vào bảng tính hoặc xử lý bằng tập lệnh. Mẫu
Báo cáo về thành phần kết hợp
Tệp composables.txt nêu chi tiết từng hàm có khả năng kết hợp cho mô-đun nhất định, bao gồm cả độ ổn định của các tham số của hàm đó và liệu hàm đó có thể khởi động lại hay có thể bỏ qua hay không. Sau đây là một ví dụ giả định từ JetSnack:
restartable skippable scheme("[androidx.compose.ui.UiComposable]") fun SnackCollection(
stable snackCollection: SnackCollection
stable onSnackClick: Function1<Long, Unit>
stable modifier: Modifier? = @static Companion
stable index: Int = @static 0
stable highlight: Boolean = @static true
)
Trong ví dụ này, mọi tham số của SnackCollection đều được đánh dấu là stable, vì vậy, Compose sẽ so sánh từng tham số bằng cách sử dụng tính bằng nhau về cấu trúc (Object.equals()). Mặc dù các tham số stable là lựa chọn lý tưởng cho các giá trị gốc và các lớp dữ liệu phẳng, nhỏ với các quy trình kiểm tra .equals() không tốn kém, nhưng việc buộc các mô hình chứa tập hợp (chẳng hạn như SnackCollection gói List<Snack>) phải là stable sẽ khiến Compose gọi .equals() trên mỗi mục trong mỗi lần kết hợp lại. Khi bật Chế độ bỏ qua hữu hiệu, bạn nên giữ lại các mô hình chứa tập hợp unstable để Compose so sánh các mô hình đó bằng cách sử dụng tính bằng nhau của thực thể (===).
Ngoài ra, hãy xem xét một ví dụ khác được tạo khi tắt Chế độ bỏ qua hữu hiệu:
restartable scheme("[androidx.compose.ui.UiComposable]") fun HighlightedSnacks(
stable index: Int
unstable snacks: List<Snack>
stable onSnackClick: Function1<Long, Unit>
stable modifier: Modifier? = @static Companion
)
Khi chế độ bỏ qua hữu hiệu bị tắt (trước Kotlin 2.0.20), thành phần kết hợp HighlightedSnacks không thể bỏ qua được. Compose không bao giờ bỏ qua thành phần kết hợp này trong quá trình kết hợp lại, ngay cả khi không có tham số nào thay đổi, do tham số unstable snacks.
Khi bật Chế độ bỏ qua hữu hiệu (mặc định trong Kotlin 2.0.20 trở lên), HighlightedSnacks được đánh dấu là skippable và Compose so sánh tham số unstable snacks bằng cách sử dụng tính bằng nhau của thực thể (===). Do đó, Compose sẽ bỏ qua HighlightedSnacks nếu cùng một tệp đối chiếu List được truyền và chỉ kết hợp lại nếu một thực thể List mới được phân bổ được truyền.
Báo cáo về các lớp
Tệp classes.txt này chứa một báo cáo tương tự về các lớp trong mô-đun nhất định. Đoạn mã sau đây là kết quả đối với lớp Snack:
unstable class Snack {
stable val id: Long
stable val name: String
stable val imageUrl: String
stable val price: Long
stable val tagline: String
unstable val tags: Set<String>
<runtime stability> = Unstable
}
Để tham khảo, sau đây là định nghĩa của Snack:
data class Snack(
val id: Long,
val name: String,
val imageUrl: String,
val price: Long,
val tagline: String = "",
val tags: Set<String> = emptySet()
)
Trình biên dịch Compose đã đánh dấu Snack là không ổn định. Nguyên nhân là do kiểu của tham số tags là Set<String>. Đây là một kiểu dữ liệu bất biến, vì không phải là MutableSet. Tuy nhiên, về bản chất thì các lớp tập hợp tiêu chuẩn như Set, List và Map đều là các giao diện. Như vậy, phương thức triển khai cơ bản có thể vẫn có khả năng biến đổi.
Ví dụ: bạn có thể viết val set: Set<String> = mutableSetOf("foo"). Biến này là hằng số và kiểu dữ liệu đã khai báo của nó là không biến đổi được, nhưng vẫn có thể biến đổi phương thức triển khai. Trình biên dịch Compose không thể chắc chắn về tính bất biến của lớp này vì nó chỉ nhìn thấy kiểu dữ liệu đã khai báo. Do đó công cụ này đánh dấu tags là không ổn định.