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ỗiNavEntrytrong ngăn xếp lui. Phương thức này nhậnNavEntrylà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á theocontentKeycủa mục nhập. Bạn có thể dùngCompositionLocalProviderđể 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ọientry.Content()trong phương thức này.onPop– Một lệnh gọi lại được gọi khiNavEntryđã bị xoá khỏi ngăn xếp lui và đã rời khỏi thành phần. Nó nhận đượccontentKeycủa mục đã xoá. Sử dụngcontentKeyđể 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ácNavEntrymà bạn có thể dùng vớiNavDisplay. - Cung cấp trình trang trí của bạn trực tiếp cho
NavDisplaybằng cách sử dụng tham sốentryDecorators.NavDisplaygọirememberDecoratedNavEntriestheo 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
NavEntrytrong ngăn xếp lui. Ví dụ:ViewModelStoreNavEntryDecoratortạo mộtViewModelStorecho mọiNavEntry. - Truyền kết quả và giao tiếp giữa các đích đến. Ví dụ:
ResultEventBusNavEntryDecoratorcung cấpResultEventBuscho 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ộtViewModelgiữ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
NavEntrybằ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,ViewModelStoreNavEntryDecoratorsẽ 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
NavEntryduy 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.