Bỏ qua hữu hiệu là một chế độ có trong trình biên dịch Compose. Khi được bật, chế độ này sẽ thay đổi hành vi của trình biên dịch theo hai cách:
- Các thành phần kết hợp có tham số không ổn định sẽ trở thành có thể bỏ qua
- Hàm lambda có các giá trị thu nạp không ổn định sẽ được ghi nhớ
Bật chế độ bỏ qua hữu hiệu
Chế độ bỏ qua hữu hiệu được bật theo mặc định trong Kotlin 2.0.20.
Để bật tính năng bỏ qua mạnh mẽ cho một mô-đun Gradle trong bản phát hành trước 2.0.20, hãy thêm tuỳ chọn sau vào khối composeCompiler của cấu hình Gradle:
android { ... }
composeCompiler {
enableStrongSkippingMode = true
}
Khả năng bỏ qua thành phần kết hợp
Chế độ bỏ qua mạnh mẽ nới lỏng một số quy tắc ổn định thường được trình biên dịch Compose áp dụng khi bỏ qua và các hàm composable. Theo mặc định, trình biên dịch Compose sẽ đánh dấu một hàm composable là có thể bỏ qua nếu tất cả đối số của hàm đó đều có giá trị ổn định. Chế độ bỏ qua hữu hiệu sẽ thay đổi điều này.
Khi bạn bật tính năng bỏ qua mạnh, tất cả các hàm composable có thể khởi động lại đều có thể bỏ qua. Điều này áp dụng cho dù các hàm đó có tham số không ổn định hay không. Các hàm composable không thể khởi động lại vẫn không thể bỏ qua.
Trường hợp nên bỏ qua
Để xác định xem có nên bỏ qua một thành phần kết hợp trong quá trình kết hợp lại hay không, Compose sẽ so sánh giá trị của từng tham số với giá trị trước đó. Loại so sánh phụ thuộc vào tính ổn định của tham số.
- Tham số không ổn định được so sánh bằng cách sử dụng tính cân bằng thực thể (
===) - Tham số ổn định được so sánh bằng cách sử dụng tính bằng nhau của đối tượng (
Object.equals())
Nếu tất cả tham số đều đáp ứng các yêu cầu này, thì Compose sẽ bỏ qua thành phần kết hợp trong quá trình kết hợp lại.
Bạn có thể muốn một composable chọn không tham gia tính năng bỏ qua mạnh. Tức là bạn có thể muốn một thành phần kết hợp có thể khởi động lại nhưng không thể bỏ qua. Trong trường hợp này, hãy sử dụng chú thích @NonSkippableComposable.
@NonSkippableComposable
@Composable
fun MyNonSkippableComposable {}
Chú thích các lớp là ổn định
Nếu bạn muốn so sánh một đối tượng bằng cách sử dụng tính bằng nhau của đối tượng (Object.equals()) thay vì tính bằng nhau của thực thể (===), hãy tiếp tục chú thích lớp đã cho bằng @Stable hoặc @Immutable.
Hãy lưu ý những điểm đánh đổi sau đây trước khi thêm @Stable hoặc @Immutable:
- Các lớp có thuộc tính ổn định trong mô-đun Compose đã ổn định: Một lớp có các thuộc tính
valthuộc loại ổn định trong một mô-đun được biên dịch bằng trình biên dịch Compose sẽ tự động được suy luận là ổn định và sử dụng.equals()mà không cần@Immutablehoặc@Stable. - Chỉ chú thích các lớp có quy trình kiểm tra
.equals()đơn giản: Thêm@Stablehoặc@Immutablekhi trình biên dịch không thể suy luận độ ổn định (chẳng hạn như các lớp từ mô-đun không phải Compose) và các thực thể mới có giá trị giống hệt nhau thường được phân bổ, miễn là quy trình kiểm tra.equals()của lớp đó không tốn kém. - Hãy thận trọng khi chú thích các mô hình có tập hợp: Việc thêm
@Stablehoặc@Immutablevào các mô hình chứa tập hợp (hoặc thay thếListbằngImmutableList) sẽ khiến Compose so sánh mọi phần tử trong tập hợp với.equals()trên mỗi lượt kết hợp lại. Đối với các tập hợp hoặc mô hình lớn được dùng trong bố cục tải từng phần (LazyColumn,LazyRow,LazyGrid), việc so sánh mọi phần tử có thể chậm hơn so với việc sử dụng tính bằng nhau của thực thể (===) hoặc kết hợp lại trực tiếp.
Ghi nhớ lambda
Chế độ bỏ qua hữu hiệu cũng cho phép ghi nhớ nhiều lambda hơn bên trong các thành phần kết hợp. Khi bật chế độ bỏ qua hữu hiệu, mọi lambda trong một hàm composable sẽ tự động được ghi nhớ.
Ví dụ
Để ghi nhớ các hàm lambda bên trong thành phần kết hợp khi sử dụng tính năng bỏ qua mạnh, trình biên dịch sẽ gói hàm lambda của bạn bằng lệnh gọi remember. Nó được khoá bằng
các bản chụp của lambda.
Hãy xem xét trường hợp bạn có một lambda như trong ví dụ sau:
@Composable
fun MyComposable(unstableObject: Unstable, stableObject: Stable) {
val lambda = {
use(unstableObject)
use(stableObject)
}
}
Khi bật chế độ bỏ qua hữu hiệu, trình biên dịch sẽ ghi nhớ lambda bằng cách gói lambda đó trong một lệnh gọi remember:
@Composable
fun MyComposable(unstableObject: Unstable, stableObject: Stable) {
val lambda = remember(unstableObject, stableObject) {
{
use(unstableObject)
use(stableObject)
}
}
}
Các khoá tuân theo cùng quy tắc so sánh như các hàm composable. Thời gian chạy so sánh các khoá không ổn định bằng cách sử dụng tính bằng nhau của thực thể. Hàm này so sánh các khoá ổn định bằng cách sử dụng tính bằng nhau của đối tượng.
Ghi nhớ và kết hợp lại
Tính năng tối ưu hoá này làm tăng đáng kể số lượng thành phần kết hợp mà thời gian chạy bỏ qua trong quá trình kết hợp lại. Nếu không có tính năng ghi nhớ, thì thời gian chạy có nhiều khả năng sẽ phân bổ một lambda mới cho bất kỳ thành phần kết hợp nào lấy tham số lambda trong quá trình kết hợp lại. Do đó, lambda mới có các tham số không bằng với thành phần cuối cùng. Điều này dẫn đến việc tái kết hợp.
Tránh ghi nhớ
Nếu bạn có một hàm lambda mà bạn không muốn ghi nhớ, hãy sử dụng chú thích @DontMemoize.
val lambda = @DontMemoize {
...
}
Kích thước APK
Khi được biên dịch, các Thành phần kết hợp có thể bỏ qua sẽ tạo ra nhiều mã hơn so với các thành phần kết hợp không thể bỏ qua. Khi bạn bật tính năng bỏ qua mạnh, trình biên dịch sẽ đánh dấu gần như tất cả thành phần kết hợp là có thể bỏ qua và gói tất cả lambda trong một remember{...}. Do đó, việc bật chế độ bỏ qua hữu hiệu sẽ có tác động rất nhỏ đến kích thước APK của ứng dụng.
Việc bật tính năng bỏ qua mạnh mẽ trong Now In Android đã tăng kích thước tệp APK thêm 4 kB. Sự khác biệt về kích thước chủ yếu phụ thuộc vào số lượng thành phần kết hợp không thể bỏ qua trước đó có trong ứng dụng nhất định, nhưng sự khác biệt này tương đối nhỏ.