Áp dụng logic hoặc trình bao bọc cho đích đến

Bạn có thể cung cấp thêm thông tin hoặc áp dụng cùng một logic cho các đích đến bằng cách sử dụng lớp NavEntryDecorator. Lớp này bao bọc từng NavEntry trong một ngăn xếp lui bằng một hàm composable. Nói cách khác, nó trang trí nội dung của mục nhập.

Tạo một đối tượng trang trí tuỳ chỉnh

Để tạo một đối tượng trang trí, hãy mở rộng lớp NavEntryDecorator và ghi đè các phương thức sau:

  • decorate – Một hàm lambda có thể kết hợp được gọi cho mỗi NavEntry trong ngăn xếp lui. Phương thức này nhận NavEntry làm tham số. Điều này cho phép bạn tạo các đối tượng trạng thái được khoá theo contentKey của mục nhập. Bạn có thể dùng CompositionLocalProvider để cung cấp các phần phụ thuộc cho nội dung của mục nhập. Bạn cũng có thể bao quanh nội dung bằng một hàm composable hoặc kích hoạt các hiệu ứng phụ. Bạn phải luôn gọi entry.Content() trong phương thức này.
  • onPop – Một lệnh gọi lại được gọi khi NavEntry đã bị xoá khỏi ngăn xếp lui và đã rời khỏi thành phần. Nó nhận được contentKey của mục đã xoá. Sử dụng contentKey để xác định và dọn dẹp mọi trạng thái liên kết với mục đó.

Ví dụ sau đây mở rộng lớp NavEntryDecorator để tạo một trình trang trí tuỳ chỉnh.

// import androidx.navigation3.runtime.NavEntryDecorator
class CustomNavEntryDecorator<T : Any> : NavEntryDecorator<T>(
    decorate = { entry ->
        Log.d("CustomNavEntryDecorator", "entry with ${entry.contentKey} entered composition and was decorated")
        entry.Content()
    },
    onPop = { contentKey -> Log.d("CustomNavEntryDecorator", "entry with $contentKey was popped") }
)

Nếu đối tượng trang trí của bạn cần quyền truy cập vào state, hãy tạo một hàm composable để tạo state đó, sau đó dùng hàm này để tạo đối tượng trang trí. Để biết ví dụ về cách triển khai, hãy xem mã nguồn của rememberSaveableStateHolderNavEntryDecorator. Thao tác này sẽ tạo trạng thái (SaveableStateHolder) và dùng trạng thái đó để tạo thành phần trang trí.

Trang trí ngăn xếp lui

Sau khi tạo NavEntryDecorator, hãy trang trí các mục trong ngăn xếp lui theo một trong hai cách:

  • Sử dụng rememberDecoratedNavEntries. Hàm này hữu ích khi bạn có nhiều ngăn xếp lui, mỗi ngăn xếp có một nhóm đối tượng trang trí riêng (xem công thức mã này để biết thêm chi tiết). Hàm này trả về một danh sách được trang trí gồm các NavEntry mà bạn có thể dùng với NavDisplay.
  • Cung cấp trình trang trí của bạn trực tiếp cho NavDisplay bằng cách sử dụng tham số entryDecorators. NavDisplay gọi rememberDecoratedNavEntries theo cách không rõ ràng và hiển thị các mục được trang trí.

Thêm trình trang trí mặc định

Navigation 3 có một đối tượng trang trí mặc định tên là SaveableStateHolderNavEntryDecorator, cho phép giữ lại trạng thái của NavEntry trong quá trình thay đổi cấu hình và bị buộc tắt. Thành phần này bao bọc nội dung NavEntry bằng một SaveableStateProvider, cho phép các lệnh gọi rememberSaveable bên trong nội dung NavEntry hoạt động đúng cách.

Trừ phi lớp trang trí của bạn cung cấp một SaveableStateProvider, nếu không, bạn nên thêm SaveableStateHolderNavEntryDecorator làm lớp trang trí đầu tiên trong danh sách các lớp trang trí được cung cấp. Thao tác này được tạo bằng rememberSaveableStateHolderNavEntryDecorator.

Ví dụ:

// import androidx.navigation3.runtime.rememberSaveableStateHolderNavEntryDecorator
NavDisplay(
    entryDecorators = listOf(
        rememberSaveableStateHolderNavEntryDecorator(),
        remember { CustomNavEntryDecorator() }
    ),
    // ...
)

Kết quả về thẻ và vé khi sử dụng ResultEventBusNavEntryDecorator

Kể từ Navigation 3 1.2.0, bạn có thể dùng ResultEventBusNavEntryDecorator để cung cấp ResultEventBus cho mỗi NavEntry bằng thành phần cục bộ LocalResultEventBus.

Theo mặc định, rememberResultEventBusNavEntryDecorator sẽ tạo và ghi nhớ phiên bản ResultEventBus của riêng nó ở bên trong bằng cách sử dụng rememberResultEventBus. Nếu cần truy cập vào tuyến nghe sự kiện bên ngoài hệ phân cấp trình trang trí (chẳng hạn như ở cấu trúc ứng dụng cấp cao nhất), bạn có thể nâng ResultEventBus bằng cách gọi rememberResultEventBus và truyền nó đến rememberResultEventBusNavEntryDecorator(resultEventBus):

val resultEventBus = rememberResultEventBus()

NavDisplay(
    /* ... */
    entryDecorators = listOf(
        rememberSaveableStateHolderNavEntryDecorator(),
        rememberResultEventBusNavEntryDecorator(resultEventBus = resultEventBus)
    )
)

Để biết thêm thông tin về cách gửi và theo dõi kết quả, hãy xem phần Trả về kết quả.

Trường hợp sử dụng decorator

Sử dụng một decorator để:

  • Tạo một phần phụ thuộc cho mọi NavEntry trong ngăn xếp lui. Ví dụ: ViewModelStoreNavEntryDecorator tạo một ViewModelStore cho mọi NavEntry.
  • Truyền kết quả và giao tiếp giữa các đích đến. Ví dụ: ResultEventBusNavEntryDecorator cung cấp ResultEventBus cho các đích đến trong ngăn xếp lui.
  • Phạm vi một đối tượng cho nhiều NavEntry. Ví dụ: để chia sẻ một ViewModel giữa nhiều mục.
  • Thực hiện cùng một thao tác cho nhiều NavEntry. Ví dụ: để thực hiện các thao tác ghi nhật ký, gỡ lỗi hoặc theo dõi cho từng mục.
  • Gói NavEntry bằng cùng một hàm composable.
  • Dọn dẹp trạng thái liên kết với các NavEntry. Ví dụ: khi một mục nhập bị xoá khỏi ngăn xếp lui, ViewModelStoreNavEntryDecorator sẽ xoá ViewModelStore được liên kết.

Không dùng trình trang trí để:

  • Truyền một phần phụ thuộc đến một NavEntry duy nhất.
  • Cung cấp các phần phụ thuộc có phạm vi rộng hơn ngăn xếp lui.

Trong cả hai trường hợp này, hãy truyền trực tiếp phần phụ thuộc khi tạo NavEntry thay vào đó.

Để xem thêm các đoạn mã ví dụ, hãy xem NavEntryDecorator.