Độ ổn định trong Compose

Compose coi các loại là ổn định hoặc không ổn định. Kiểu là ổn định nếu kiểu này không thể thay đổi, hoặc nếu Compose có thể biết được giá trị của kiểu đó có thay đổi giữa các lần kết hợp lại hay không. Một kiểu không ổn định nếu Compose không thể biết liệu giá trị của kiểu đó có thay đổi giữa các lần kết hợp lại hay không.

Compose sử dụng độ ổn định của các tham số của một thành phần kết hợp để xác định xem liệu thành phần đó có thể bỏ qua thành phần kết hợp đó trong quá trình kết hợp lại hay không:

  • Tham số ổn định:Nếu một thành phần kết hợp có các tham số ổn định không thay đổi, thì Compose sẽ bỏ qua tham số đó.
  • Tham số không ổn định: Nếu một thành phần kết hợp có tham số không ổn định, thì Compose sẽ luôn kết hợp lại tham số đó khi kết hợp lại thành phần mẹ của thành phần.

Nếu ứng dụng của bạn có nhiều thành phần không ổn định một cách không cần thiết mà Compose luôn kết hợp lại, thì bạn có thể nhận thấy các vấn đề về hiệu suất và các vấn đề khác.

Tài liệu này trình bày chi tiết cách bạn có thể tăng độ ổn định của ứng dụng để cải thiện hiệu suất và trải nghiệm tổng thể của người dùng.

Đối tượng bất biến

Các đoạn mã sau đây trình bày các nguyên tắc chung đằng sau tính ổn định và khả năng kết hợp lại.

Lớp Contact là lớp dữ liệu không thể thay đổi. Điều này là do tất cả các tham số của lớp này đều là dữ liệu gốc được xác định bằng từ khoá val. Sau khi tạo một thực thể của Contact, bạn không thể thay đổi giá trị của các thuộc tính của đối tượng. Nếu đã cố gắng làm như vậy, bạn sẽ tạo một đối tượng mới.

data class Contact(val name: String, val number: String)

Thành phần kết hợp ContactRow có tham số thuộc loại Contact.

@Composable
fun ContactRow(contact: Contact, modifier: Modifier = Modifier) {
   var selected by remember { mutableStateOf(false) }

   Row(modifier) {
      ContactDetails(contact)
      ToggleButton(selected, onToggled = { selected = !selected })
   }
}

Hãy xem xét điều gì sẽ xảy ra khi người dùng nhấp vào nút bật tắt và trạng thái selected sẽ thay đổi:

  1. Compose sẽ đánh giá xem có cần kết hợp lại mã bên trong ContactRow hay không.
  2. Hàm này thấy rằng đối số duy nhất cho ContactDetails thuộc kiểu Contact.
  3. Do Contact là lớp dữ liệu bất biến, nên Compose chắc chắn rằng không có đối số nào cho ContactDetails thay đổi.
  4. Do đó, Compose bỏ qua ContactDetails và không kết hợp lại lớp này.
  5. Mặt khác, các đối số cho ToggleButton đã thay đổi và Compose kết hợp lại thành phần đó.

Đối tượng có thể thay đổi

Mặc dù ví dụ trước sử dụng đối tượng không thể biến đổi, nhưng bạn vẫn có thể tạo một đối tượng có thể biến đổi. Hãy xem xét đoạn mã sau:

data class Contact(var name: String, var number: String)

Vì mỗi tham số của Contact hiện là một var nên lớp này không thể thay đổi được nữa. Nếu các thuộc tính của nút này thay đổi, thì Compose sẽ không biết. Điều này là do Compose chỉ theo dõi các thay đổi đối với đối tượng Trạng thái Compose.

Compose coi một lớp như vậy là không ổn định. Compose không bỏ qua quá trình kết hợp lại các lớp không ổn định. Do đó, nếu Contact được xác định theo cách này, ContactRow trong ví dụ trước sẽ kết hợp lại mỗi khi selected thay đổi.

Triển khai trong Compose

Mặc dù không quan trọng, nhưng việc xem xét chính xác cách Compose xác định những hàm cần bỏ qua trong quá trình kết hợp lại có thể giúp ích cho bạn.

Khi chạy trên mã, trình biên dịch Compose sẽ đánh dấu từng hàm và loại bằng một trong vài thẻ. Các thẻ này phản ánh cách Compose xử lý hàm hoặc kiểu trong quá trình kết hợp lại.

Hàm

Compose có thể đánh dấu các hàm là skippable hoặc restartable. Xin lưu ý rằng thuộc tính này có thể đánh dấu một hàm là một, cả hai hoặc không phải hàm nào trong số này:

  • Có thể bỏ qua: Nếu trình biên dịch đánh dấu một thành phần kết hợp là có thể bỏ qua, thì Compose có thể bỏ qua thành phần đó trong quá trình kết hợp lại nếu tất cả đối số của nó bằng với các giá trị trước đó.
  • Có thể khởi động lại: Một thành phần kết hợp có thể khởi động lại đóng vai trò là "phạm vi" khi quá trình kết hợp lại có thể bắt đầu. Nói cách khác, hàm có thể là điểm truy cập để Compose có thể bắt đầu thực thi lại mã để kết hợp lại sau khi thay đổi trạng thái.

Loại

Compose đánh dấu các loại là không thể thay đổi hoặc ổn định. Mỗi kiểu là một hoặc kiểu khác:

  • Không thể thay đổi: Compose đánh dấu một loại là không thể thay đổi nếu giá trị của các thuộc tính không bao giờ có thể thay đổi và tất cả các phương thức đều trong suốt theo tham chiếu.
    • Lưu ý rằng tất cả các loại gốc được đánh dấu là không thể thay đổi. Các API này bao gồm String, IntFloat.
  • Ổn định: Cho biết loại có thuộc tính có thể thay đổi sau khi xây dựng. Nếu và khi các thuộc tính đó thay đổi trong thời gian chạy, thì Compose sẽ nhận biết được những thay đổi đó.

Độ ổn định của quá trình gỡ lỗi

Nếu ứng dụng của bạn đang kết hợp lại một thành phần kết hợp có tham số không thay đổi, trước tiên, hãy kiểm tra định nghĩa của thành phần đó để biết các tham số có thể thay đổi rõ ràng. Compose luôn kết hợp lại một thành phần nếu bạn truyền một loại có thuộc tính var hoặc thuộc tính val sử dụng một loại không ổn định đã biết.

Để biết thông tin chi tiết về cách chẩn đoán các vấn đề phức tạp về độ ổn định trong Compose, hãy xem hướng dẫn Độ ổn định khi gỡ lỗi.

Khắc phục sự cố về độ ổn định

Để biết thông tin về cách đảm bảo quá trình triển khai Compose ổn định, hãy xem hướng dẫn Khắc phục vấn đề về tính ổn định.

Tóm tắt

Nhìn chung, bạn cần lưu ý những điểm sau:

  • Tham số: Compose xác định độ ổn định của từng tham số của các thành phần kết hợp để xác định những thành phần kết hợp nên bỏ qua trong quá trình kết hợp lại.
  • Khắc phục ngay lập tức: Nếu bạn nhận thấy thành phần kết hợp không bị bỏ qua và đang gây ra vấn đề về hiệu suất, trước tiên, bạn nên kiểm tra các nguyên nhân rõ ràng gây ra sự bất ổn định như tham số var.
  • Báo cáo trình biên dịch: Bạn có thể sử dụng báo cáo trình biên dịch để xác định độ ổn định đang được dự đoán cho các lớp của mình.
  • Bộ sưu tập: Compose luôn xem các lớp bộ sưu tập là không ổn định, chẳng hạn như List, SetMap. Lý do là vì không thể đảm bảo rằng các giá trị này là bất biến. Thay vào đó, bạn có thể dùng các tập hợp không thể thay đổi trong Kotlinx hoặc chú giải các lớp của mình là @Immutable hoặc @Stable.
  • Các mô-đun khác: Compose luôn xem là không ổn định ở vị trí của các mô-đun đó từ các mô-đun mà trình biên dịch Compose không chạy. Gói các lớp trong lớp mô hình giao diện người dùng nếu cần.

Tài liệu đọc thêm