Điều hướng mô tả cách người dùng di chuyển trong ứng dụng. Người dùng tương tác với các thành phần trên giao diện người dùng, thường là bằng cách nhấn hoặc nhấp vào các thành phần đó và ứng dụng phản hồi bằng cách hiển thị nội dung mới. Nếu muốn quay lại nội dung trước đó, người dùng sẽ sử dụng cử chỉ quay lại hoặc nhấn vào nút quay lại.
Mô hình hoá trạng thái điều hướng
Một cách thuận tiện để lập mô hình hành vi này là sử dụng ngăn xếp nội dung. Khi người dùng điều hướng tiến đến nội dung mới, nội dung đó sẽ được đẩy lên đầu ngăn xếp. Khi người dùng quay lại từ nội dung đó, nội dung đó sẽ bị đẩy ra khỏi ngăn xếp và nội dung trước đó sẽ hiển thị. Trong các thuật ngữ điều hướng, ngăn xếp này thường được gọi là ngăn xếp lui vì nó đại diện cho nội dung mà người dùng có thể quay lại.

Tạo ngăn xếp lui
Trong Navigation 3, ngăn xếp lui không thực sự chứa nội dung. Thay vào đó, tệp này chứa các tệp tham chiếu đến nội dung, được gọi là khoá. Khoá có thể là bất kỳ loại nào nhưng thường là các lớp dữ liệu đơn giản, có thể chuyển đổi tuần tự. Việc sử dụng tệp tham chiếu thay vì nội dung mang lại các lợi ích sau:
- Bạn có thể dễ dàng điều hướng bằng cách đẩy các phím vào ngăn xếp lui.
- Miễn là các khoá có thể chuyển đổi tuần tự, ngăn xếp lui có thể được lưu vào bộ nhớ cố định, cho phép ngăn xếp lui tồn tại sau khi thay đổi cấu hình và xử lý sự cố. Điều này rất quan trọng vì người dùng muốn rời khỏi ứng dụng, quay lại ứng dụng sau và tiếp tục từ nơi họ đã dừng lại với cùng nội dung đang hiển thị. Hãy xem phần Lưu ngăn xếp lui để biết thêm thông tin.
Một khái niệm chính trong API Navigation 3 là bạn sở hữu ngăn xếp lui. Thư viện:
- Dự kiến ngăn xếp lui sẽ là
List<T>
được sao lưu trạng thái tổng quan nhanh, trong đóT
là loại ngăn xếp luikeys
. Bạn có thể sử dụngAny
hoặc cung cấp các khoá có kiểu mạnh hơn của riêng mình. Khi bạn thấy các thuật ngữ "push" hoặc "pop", cách triển khai cơ bản là thêm hoặc xoá các mục khỏi cuối danh sách. - Quan sát ngăn xếp lui và phản ánh trạng thái của ngăn xếp lui trong giao diện người dùng bằng cách sử dụng
NavDisplay
.
Ví dụ sau đây cho biết cách tạo khoá và ngăn xếp lui, đồng thời sửa đổi ngăn xếp lui để phản hồi các sự kiện điều hướng của người dùng:
// Define keys that will identify content data object ProductList data class ProductDetail(val id: String) @Composable fun MyApp() { // Create a back stack, specifying the key the app should start with val backStack = remember { mutableStateListOf<Any>(ProductList) } // Supply your back stack to a NavDisplay so it can reflect changes in the UI // ...more on this below... // Push a key onto the back stack (navigate forward), the navigation library will reflect the change in state backStack.add(ProductDetail(id = "ABC")) // Pop a key off the back stack (navigate back), the navigation library will reflect the change in state backStack.removeLastOrNull() }
Giải quyết khoá đến nội dung
Nội dung được mô hình hoá trong Navigation 3 bằng NavEntry
, đây là một lớp chứa hàm có khả năng kết hợp. Thành phần này đại diện cho một đích đến – một nội dung mà người dùng có thể chuyển đến và quay lại.
NavEntry
cũng có thể chứa siêu dữ liệu – thông tin về nội dung. Các đối tượng vùng chứa (như NavDisplay
) có thể đọc siêu dữ liệu này để giúp quyết định cách hiển thị nội dung của NavEntry
. Ví dụ: siêu dữ liệu có thể được dùng để ghi đè ảnh động mặc định cho một NavEntry
cụ thể. NavEntry metadata
là một bản đồ ánh xạ các khoá String
đến các giá trị Any
, cung cấp bộ nhớ dữ liệu linh hoạt.
Để chuyển đổi key
thành NavEntry
, hãy tạo entryProvider
. Đây là một hàm chấp nhận key
và trả về NavEntry
cho key
đó. Thông số này thường được xác định là tham số lambda khi tạo NavDisplay
.
Có hai cách để tạo entryProvider
, đó là tạo trực tiếp hàm lambda hoặc sử dụng DSL entryProvider
.
Tạo trực tiếp hàm entryProvider
Thông thường, bạn tạo hàm entryProvider
bằng câu lệnh when
, với một nhánh cho mỗi khoá.
entryProvider = { key -> when (key) { is ProductList -> NavEntry(key) { Text("Product List") } is ProductDetail -> NavEntry( key, metadata = mapOf("extraDataKey" to "extraDataValue") ) { Text("Product ${key.id} ") } else -> { NavEntry(Unit) { Text(text = "Invalid Key: $it") } } } }
Sử dụng DSL entryProvider
DSL entryProvider
có thể đơn giản hoá hàm lambda của bạn bằng cách tránh việc cần phải kiểm thử theo từng loại khoá và tạo một NavEntry
cho từng loại khoá.
Sử dụng hàm tạo entryProvider
cho việc này. Phương thức này cũng bao gồm hành vi dự phòng mặc định (gửi lỗi) nếu không tìm thấy khoá.
entryProvider = entryProvider { entry<ProductList> { Text("Product List") } entry<ProductDetail>( metadata = mapOf("extraDataKey" to "extraDataValue") ) { key -> Text("Product ${key.id} ") } }
Lưu ý những điều sau trong đoạn mã:
entry
được dùng để xác địnhNavEntry
với loại và nội dung có thể kết hợp nhất địnhentry
chấp nhận tham sốmetadata
để đặtNavEntry.metadata
Hiển thị ngăn xếp lui
Ngăn xếp lui thể hiện trạng thái điều hướng của ứng dụng. Bất cứ khi nào ngăn xếp lui thay đổi, giao diện người dùng của ứng dụng sẽ phản ánh trạng thái ngăn xếp lui mới. Trong Navigation 3, NavDisplay
quan sát ngăn xếp lui và cập nhật giao diện người dùng cho phù hợp. Tạo lớp này bằng các tham số sau:
- Ngăn xếp lui – ngăn xếp này phải thuộc loại
SnapshotStateList<T>
, trong đóT
là loại của các khoá ngăn xếp lui. Đây là mộtList
có thể quan sát được để kích hoạt quá trình kết hợp lạiNavDisplay
khi giá trị này thay đổi. entryProvider
để chuyển đổi các khoá trong ngăn xếp lui thànhNavEntry
.- Không bắt buộc, hãy cung cấp một hàm lambda cho tham số
onBack
. Phương thức này được gọi khi người dùng kích hoạt một sự kiện quay lại.
Ví dụ sau đây cho thấy cách tạo NavDisplay
.
data object Home data class Product(val id: String) @Composable fun NavExample() { val backStack = remember { mutableStateListOf<Any>(Home) } NavDisplay( backStack = backStack, onBack = { backStack.removeLastOrNull() }, entryProvider = { key -> when (key) { is Home -> NavEntry(key) { ContentGreen("Welcome to Nav3") { Button(onClick = { backStack.add(Product("123")) }) { Text("Click to navigate") } } } is Product -> NavEntry(key) { ContentBlue("Product ${key.id} ") } else -> NavEntry(Unit) { Text("Unknown route") } } } ) }
Theo mặc định, NavDisplay
hiển thị NavEntry
trên cùng trong ngăn xếp lui theo bố cục ngăn đơn. Bản ghi sau đây cho thấy ứng dụng này đang chạy:

NavDisplay
với hai đích đến.Kết hợp kiến thức đã học
Sơ đồ sau đây cho thấy cách dữ liệu di chuyển giữa các đối tượng trong Navigation 3:

Sự kiện điều hướng bắt đầu thay đổi. Các khoá được thêm hoặc xoá khỏi ngăn xếp lui để phản hồi tương tác của người dùng.
Thay đổi trạng thái ngăn xếp lui sẽ kích hoạt quá trình truy xuất nội dung.
NavDisplay
(một thành phần kết hợp hiển thị ngăn xếp lui) quan sát ngăn xếp lui. Trong cấu hình mặc định, ngăn này hiển thị mục nhập ngăn xếp lui trên cùng trong một bố cục ngăn. Khi khoá trên cùng trên ngăn xếp lui thay đổi,NavDisplay
sẽ sử dụng khoá này để yêu cầu nội dung tương ứng từ trình cung cấp mục nhập.Trình cung cấp mục cung cấp nội dung. Nhà cung cấp mục nhập là một hàm phân giải khoá thành
NavEntry
. Khi nhận được khoá từNavDisplay
, trình cung cấp mục nhập sẽ cung cấpNavEntry
được liên kết, chứa cả khoá và nội dung.Nội dung hiển thị.
NavDisplay
nhậnNavEntry
và hiển thị nội dung.