Sửa đổi cảnh bằng các đối tượng trang trí cảnh

Trình trang trí cảnh cho phép bạn sửa đổi cảnh được tính toán theo chiến lược cảnh của ứng dụng. Trên thực tế, các phương thức này được dùng cho giai đoạn thứ hai của quá trình tạo nội dung mà NavDisplay hiển thị.

Phương pháp này cho phép bạn đóng gói chức năng cụ thể, chẳng hạn như hiển thị các thành phần giao diện người dùng phổ biến, vào từng trình trang trí cảnh.

Ví dụ: hãy xem xét một ứng dụng cải thiện năng suất có 3 tuyến cấp cao nhất: hộp thư đến email, hộp thư đến tin nhắn trực tiếp và chế độ xem lịch. Một ứng dụng như vậy có thể sử dụng hai trình trang trí cảnh, một trình trang trí để thêm thanh ứng dụng trên cùng hiển thị thông tin và các thành phần điều khiển cho tuyến cấp cao nhất hiện tại, và một trình trang trí khác để thêm thanh điều hướng hoặc dải điều hướng cố định để di chuyển giữa các tuyến.

Tạo chiến lược trang trí cảnh

Trình trang trí cảnh tuân theo mẫu tương tự như chiến lược cảnh. Để xác định trình trang trí cảnh, hãy triển khai giao diện SceneDecoratorStrategy. Giao diện này có một phương thức là decorateScene, tương tự như phương thức calculateScene của giao diện SceneStrategy. decorateScene xác định xem nó có thể trang trí cảnh hay không:

  • Nếu chiến lược trang trí cảnh không trang trí cảnh đầu vào, thì chiến lược này sẽ trả về cảnh đầu vào như hiện tại.
  • Nếu nên trang trí cảnh đầu vào, thì hàm này sẽ trả về một Scene mới. Nhìn chung, cảnh được trả về sẽ lấy cảnh đầu vào làm tham số và gọi phương thức content của cảnh đầu vào trong phương thức content của chính nó.

Để xác định xem có nên trang trí cảnh đầu vào hay không và trang trí như thế nào, chiến lược trang trí cảnh có thể xem xét siêu dữ liệu của cả Scene đầu vào và các mục có trong cảnh đó.

class MySceneDecoratorStrategy<T : Any> : SceneDecoratorStrategy<T> {


    override fun SceneDecoratorStrategyScope<T>.decorateScene(scene: Scene<T>): Scene<T> {
        // `shouldDecorate` determines if the scene should be decorated based on scene.metadata,
        // scene.entries.metadata, or any other relevant state.
        return if (shouldDecorate(scene)) {
            MyDecoratingScene(scene)
        } else {
            scene
        }
    }

}

data class MyDecoratingScene<T : Any>(
    val scene: Scene<T>
) : Scene<T> {

    // ...

    override val content = @Composable {
        scene.content()
    }
}

Sử dụng chiến lược trang trí cảnh

Để sử dụng chiến lược trang trí cảnh, hãy cung cấp các chiến lược đó cho NavDisplay bằng cách sử dụng tham số sceneDecoratorStrategies. Khi trang trí cảnh, NavDisplay sẽ gọi phương thức decorateScene của từng chiến lược theo thứ tự, truyền kết quả của mỗi lệnh gọi làm dữ liệu đầu vào cho lệnh gọi tiếp theo.

NavDisplay(
    // ...
    sceneDecoratorStrategies = listOf(firstSceneDecoratorStrategy, secondSceneDecoratorStrategy)
)

Các mẫu phổ biến cho trình trang trí cảnh

Khi triển khai trình trang trí cảnh, bạn cần lưu ý một số mẫu phổ biến sau:

Sao chép thuộc tính

Trong nhiều trường hợp, cảnh được trả về bằng cách trang trí một cảnh phải chứa cùng các mục và có cùng các mục trước đó như cảnh mà nó đang trang trí. Ngoài ra, có thể lớp này sẽ kế thừa (hoặc sửa đổi) siêu dữ liệu của cảnh mà lớp này đang trang trí, thay vì sử dụng hành vi mặc định. Đoạn mã sau đây minh hoạ một ví dụ về cách thực hiện việc này:

data class CopyingScene<T : Any>(
    val scene: Scene<T>
) : Scene<T> {
    override val entries = scene.entries
    override val previousEntries = scene.previousEntries
    override val metadata = scene.metadata

    // ...
}

Duy trì ảnh động

Như được trình bày chi tiết trong phần Tạo ảnh động giữa các đích đến, NavDisplay sẽ tự động tạo ảnh động cho quá trình chuyển đổi giữa các cảnh khi một khoá bắt nguồn từ lớp của cảnh hiện tại và thuộc tính key của cảnh đó thay đổi.

Khi giới thiệu trình trang trí cảnh cho ứng dụng, lớp của cảnh được trả về sau khi trang trí cảnh có thể giữ nguyên, ngay cả khi lớp của cảnh được trả về trong quá trình tính toán cảnh thay đổi. Khi điều này xảy ra và các cảnh trang trí sao chép trực tiếp key của cảnh mà chúng đang trang trí, ảnh động tích hợp sẵn sẽ không còn xảy ra vì khoá phái sinh không thay đổi.

Để duy trì tính năng hỗ trợ ảnh động tích hợp, các cảnh trang trí nên sử dụng khoá bắt nguồn từ lớp và key của cảnh do calculateScene trả về.

data class DerivedKeyScene<T : Any>(
    val scene: Scene<T>
) : Scene<T> {
    override val key = scene::class to scene.key

    // ...
}