Các phần sau đây mô tả các chiến lược lưu ngăn xếp lui và lưu trữ trạng thái liên kết với các mục trong ngăn xếp lui.
Lưu ngăn xếp lui
Việc đảm bảo trạng thái điều hướng của ứng dụng duy trì trên nhiều sự kiện trong vòng đời, bao gồm cả các thay đổi về cấu hình và quá trình bị buộc tắt là rất quan trọng để mang lại trải nghiệm tốt cho người dùng. Trong Navigation 3, bạn sở hữu ngăn xếp lui của mình, vì vậy, không có nguyên tắc nghiêm ngặt về cách bạn nên tạo hoặc lưu ngăn xếp đó. Tuy nhiên, Navigation 3 cung cấp
một phương thức tiện lợi giúp bạn có một ngăn xếp lui có thể lưu:
rememberNavBackStack.
Sử dụng rememberNavBackStack
Hàm composable rememberNavBackStack được thiết kế để tạo một ngăn xếp lui duy trì trên các thay đổi về cấu hình và bị buộc tắt.
Để rememberNavBackStack hoạt động chính xác, mỗi khoá trong ngăn xếp lui phải tuân thủ các yêu cầu cụ thể:
- Triển khai giao diện
NavKey: Mọi khoá trong ngăn xếp lui phải triển khai giao diệnNavKey. Giao diện này hoạt động như một giao diện đánh dấu báo hiệu cho thư viện rằng khoá có thể được lưu. - Có chú thích
@Serializable: Ngoài việc triển khaiNavKey, các lớp và đối tượng khoá của bạn phải được đánh dấu bằng chú thích@Serializable.
Đoạn mã sau đây cho thấy cách triển khai chính xác rememberNavBackStack:
@Serializable data object Home : NavKey @Composable fun NavBackStack() { val backStack = rememberNavBackStack(Home) }
Ghi nhớ ngăn xếp lui bằng các kiểu con của NavKey
Hàm composable rememberNavBackStack trả về NavBackStack<NavKey>.
Nếu ứng dụng của bạn xác định kiểu con riêng của NavKey mà tất cả các khoá của ứng dụng đều kế thừa, thì bạn có thể giữ nguyên kiểu đó bằng cách triển khai một hàm ghi nhớ tuỳ chỉnh như sau:
@Serializable sealed interface MyAppNavKey : NavKey @Serializable data object ScreenA: MyAppNavKey @Serializable data class ScreenB(val id: String): MyAppNavKey @Composable fun rememberMyAppNavBackStack(vararg elements: MyAppNavKey): NavBackStack<MyAppNavKey> { return rememberSerializable(serializer = serializer()) { NavBackStack(*elements) } } @Composable fun MyApp() { // defaultNavBackStack is NavBackStack<NavKey> val defaultNavBackStack = rememberNavBackStack(ScreenA) // myAppNavBackStack is NavBackStack<MyAppNavKey> val myAppNavBackStack = rememberMyAppNavBackStack(ScreenA) }
Để xem thêm các ví dụ (bao gồm cả cách xử lý tính đa hình mở), hãy xem
NavBackStackSamples.
Cách thay thế: Lưu trữ trong ViewModel
Một phương pháp khác để quản lý ngăn xếp lui là lưu trữ ngăn xếp đó trong ViewModel.
Để duy trì trạng thái trong quá trình bị buộc tắt khi sử dụng ViewModel hoặc bất kỳ bộ nhớ tuỳ chỉnh nào khác, bạn cần:
- Đảm bảo các khoá của bạn có thể được tuần tự hoá: Giống như với
rememberNavBackStack, các khoá điều hướng của bạn phải có thể được tuần tự hoá. - Xử lý quá trình chuyển đổi tuần tự và giải tuần tự hoá theo cách thủ công: Bạn chịu trách nhiệm
lưu thủ công bản trình bày đã chuyển đổi tuần tự của từng khoá vào bộ nhớ liên tục và
giải tuần tự hoá khoá đó từ bộ nhớ liên tục (ví dụ:
SharedPreferences, cơ sở dữ liệu hoặc tệp) khi ứng dụng của bạn chuyển sang chạy ở chế độ nền hoặc đang được khôi phục.
Phạm vi ViewModel cho NavEntry
ViewModels được dùng để giữ lại trạng thái liên quan đến giao diện người dùng trên các thay đổi về cấu hình, chẳng hạn như thao tác xoay màn hình. Theo mặc định, ViewModels được đặt phạm vi cho ViewModelStoreOwner gần nhất, thường là Activity hoặc Fragment.
Tuy nhiên, bạn có thể muốn đặt phạm vi ViewModel cho một NavEntry cụ thể (tức là một màn hình hoặc đích đến cụ thể) trên ngăn xếp lui, thay vì toàn bộ Activity. Điều này đảm bảo rằng trạng thái của ViewModel chỉ được giữ lại khi NavEntry cụ thể đó là một phần của ngăn xếp lui và sẽ bị xoá khi NavEntry được bật.
Thư viện bổ trợ androidx.lifecycle:lifecycle-viewmodel-navigation3 cung cấp
một NavEntryDecorator giúp thực hiện việc này. Trình trang trí này cung cấp một ViewModelStoreOwner cho mỗi NavEntry. Khi bạn tạo một ViewModel bên trong nội dung của NavEntry (ví dụ: sử dụng viewModel() trong Compose), thì ViewModel đó sẽ tự động được đặt phạm vi cho khoá của NavEntry cụ thể đó trên ngăn xếp lui. Điều này có nghĩa là ViewModel được tạo khi NavEntry được thêm vào ngăn xếp lui và bị xoá khi NavEntry bị xoá.
Để sử dụng NavEntryDecorator cho việc đặt phạm vi ViewModel cho NavEntry, hãy làm theo
các bước sau:
- Thêm phần phụ thuộc
androidx.lifecycle:lifecycle-viewmodel-navigation3vào tệpapp/build.gradle.kts. - Thêm
rememberSaveableStateHolderNavEntryDecorator()mặc định vào danh sáchentryDecoratorskhi tạoNavDisplay. - Thêm
rememberViewModelStoreNavEntryDecorator()vào danh sáchentryDecorators.
NavDisplay( entryDecorators = listOf( // Add the default decorators for managing scenes and saving state rememberSaveableStateHolderNavEntryDecorator(), // Then add the view model store decorator rememberViewModelStoreNavEntryDecorator() ), backStack = backStack, entryProvider = entryProvider { }, )