Chế độ bỏ qua mạnh

Mạnh bỏ qua là một chế độ có trong trình biên dịch Compose. Khi được bật, thuộc tính này sẽ thay đổi hành vi của trình biên dịch theo 2 cách:

  • Các thành phần kết hợp có tham số không ổn định sẽ có thể bỏ qua
  • Lambda có ảnh chụp không ổn định sẽ được ghi nhớ

Bật chế độ bỏ qua mạnh

Để bật tính năng bỏ qua mạnh cho một mô-đun Gradle, hãy đưa tuỳ chọn sau vào khối composeCompiler của cấu hình Gradle:

composeCompiler {
   enableStrongSkipping = true
}

Khả năng bỏ qua của thành phần kết hợp

Chế độ bỏ qua mạnh giúp giảm một số quy tắc về độ ổn định mà trình biên dịch Compose thường áp dụng khi nói đến các hàm bỏ qua và hàm có khả năng kết hợp. Theo mặc định, trình biên dịch Compose sẽ đánh dấu một hàm có khả năng kết hợp là có thể bỏ qua nếu tất cả các đối số của hàm đó đều có giá trị ổn định. Chế độ bỏ qua mạnh sẽ thay đổi điều này.

Khi bật tính năng bỏ qua mạnh, tất cả các hàm có khả năng kết hợp có thể khởi động lại đều có thể bỏ qua. Điều này áp dụng cho dù các thử nghiệm có thông số không ổn định hay không. Các hàm có khả năng kết hợp không khởi động lại vẫn không thể bỏ qua.

Thời điểm bỏ qua

Để xác định xem có 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 đó của chúng. Loại phép so sánh phụ thuộc vào độ ổn định của tham số.

  • Các tham số không ổn định được so sánh bằng cách sử dụng đẳng thức thực thể (===)
  • Các tham số ổn định được so sánh bằng cách sử dụng đẳng thức đối tượng (Object.equals())

Nếu tất cả tham số đều đáp ứng các yêu cầu này, 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 thành phần kết hợp chọn không sử dụng chế độ bỏ qua mạnh. Tức là bạn nên có 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ú giải @NonSkippableComposable.

@NonSkippableComposable
@Composable
fun MyNonSkippableComposable {}

Chú thích các lớp là ổn định

Nếu bạn muốn một đối tượng sử dụng đẳng thức đối tượng thay vì đẳng thức thực thể, hãy tiếp tục chú giải lớp đã cho bằng @Stable. Ví dụ về trường hợp bạn có thể phải làm việc này là khi quan sát toàn bộ danh sách đối tượng, các nguồn dữ liệu như Room sẽ phân bổ các đối tượng mới cho mỗi mục trong danh sách bất cứ khi nào một trong các đối tượng đó thay đổi.

Ghi nhớ Lambda

Chế độ bỏ qua mạnh cũng tạo điều kiện ghi nhớ các lambda nhiều hơn bên trong thành phần kết hợp. Khi bật chế độ bỏ qua mạnh, mọi lambda bên trong một hàm có khả năng kết hợp sẽ tự động được ghi nhớ.

Ví dụ

Để ghi nhớ 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 lambda của bạn bằng lệnh gọi remember. Nó được khoá bằng các ảnh chụp của lambda.

Hãy xem xét trường hợp bạn có hàm lambda như trong ví dụ sau:

@Composable
fun MyComposable(unstableObject: Unstable, stableObject: Stable) {
    val lambda = {
        use(unstableObject)
        use(stableObject)
    }
}

Khi bật tính năng bỏ qua mạnh, trình biên dịch ghi nhớ lambda bằng cách gói hàm này trong lệnh gọi remember:

@Composable
fun MyComposable(unstableObject: Unstable, stableObject: Stable) {
    val lambda = remember(unstableObject, stableObject) {
        {
            use(unstableObject)
            use(stableObject)
        }
    }
}

Các khoá này tuân theo cùng quy tắc so sánh như các hàm có khả năng kết hợp. Môi trường thời gian chạy so sánh các khoá không ổn định bằng cách sử dụng đẳng thức thực thể. Cấu trúc này so sánh các khoá ổn định bằng cách sử dụng đẳng thức đố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 ghi nhớ, thời gian chạy rất có 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 nhận tham số lambda trong quá trình kết hợp lại. Do đó, hàm lambda mới có các tham số không bằng với thành phần kết hợp cuối cùng. Điều này dẫn đến quá trình kết hợp lại.

Tránh ghi nhớ

Nếu bạn có một lambda mà bạn không muốn ghi nhớ, hãy sử dụng chú giải @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ậ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ả cá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 mạnh chỉ 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 trong Now In Android đã tăng kích thước APK thêm 4kB. Sự khác biệt về kích thước phần lớn phụ thuộc vào số lượng thành phần kết hợp không thể bỏ qua trước đây đã có trong ứng dụng nhất định, nhưng các thành phần này tương đối nhỏ.