Navigasi menjelaskan cara pengguna berpindah-pindah di aplikasi Anda. Pengguna berinteraksi dengan elemen UI, biasanya dengan mengetuk atau mengkliknya, dan aplikasi merespons dengan menampilkan konten baru. Jika ingin kembali ke konten sebelumnya, pengguna dapat menggunakan gestur kembali atau mengetuk tombol kembali.
Membuat model status navigasi
Cara mudah untuk membuat model perilaku ini adalah dengan tumpukan konten. Saat pengguna menavigasi ke depan ke konten baru, konten tersebut akan dikirim ke bagian atas stack. Saat mereka kembali dari konten tersebut, konten tersebut akan dikeluarkan dari tumpukan dan konten sebelumnya akan ditampilkan. Dalam istilah navigasi, stack ini biasanya disebut sebagai data sebelumnya karena mewakili konten yang dapat dibuka kembali oleh pengguna.
Membuat data sebelumnya
Di Navigation 3, data sebelumnya tidak benar-benar berisi konten. Sebagai gantinya, peta ini berisi referensi ke konten, yang dikenal sebagai kunci. Kunci dapat berupa jenis apa pun, tetapi biasanya berupa class data sederhana yang dapat diserialisasi. Menggunakan referensi, bukan konten, memiliki manfaat berikut:
- Navigasi dapat dilakukan dengan mudah dengan mengirim kunci ke data sebelumnya.
- Selama kunci dapat diserialisasi, data sebelumnya dapat disimpan ke penyimpanan persisten, sehingga dapat bertahan saat terjadi perubahan konfigurasi dan penghentian proses. Hal ini penting karena pengguna berharap dapat keluar dari aplikasi Anda, kembali ke aplikasi tersebut nanti, dan melanjutkan aktivitas terakhir mereka dengan konten yang sama ditampilkan. Lihat Menyimpan data sebelumnya untuk mengetahui informasi selengkapnya.
Konsep utama dalam Navigation 3 API adalah Anda memiliki data sebelumnya. Library:
- Mengharapkan bahwa data sebelumnya akan menjadi
List<T>yang didukung status snapshot, denganTadalah jeniskeysdata sebelumnya. Anda dapat menggunakanAnyatau memberikan kunci yang diketik lebih kuat. Saat Anda melihat istilah "push" atau "pop", implementasi yang mendasarinya adalah menambahkan atau menghapus item dari akhir daftar. - Mengamati data sebelumnya dan mencerminkan statusnya di UI menggunakan
NavDisplay.
Contoh berikut menunjukkan cara membuat kunci dan data sebelumnya, serta mengubah data sebelumnya sebagai respons terhadap peristiwa navigasi pengguna:
// 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() }
Menyelesaikan kunci ke konten
Konten dimodelkan di Navigation 3 menggunakan NavEntry, yang merupakan class
yang berisi fungsi composable. Class ini mewakili tujuan - satu bagian
konten yang dapat dibuka pengguna dengan menavigasi ke depan dan ke belakang.
NavEntry juga dapat berisi metadata, yaitu informasi tentang konten. Metadata ini dapat dibaca oleh objek container, seperti NavDisplay, untuk membantu objek tersebut memutuskan cara menampilkan konten NavEntry. Misalnya, metadata dapat
digunakan untuk mengganti animasi default untuk NavEntry tertentu. NavEntry
metadata adalah peta kunci String ke nilai Any, yang menyediakan penyimpanan data
serbaguna.
Untuk mengonversi key menjadi NavEntry, buat Penyedia Entri. Ini adalah
fungsi yang menerima key dan menampilkan NavEntry untuk key tersebut. Biasanya,
ini didefinisikan sebagai parameter lambda saat membuat NavDisplay.
Ada dua cara untuk membuat Penyedia Entri, baik dengan membuat fungsi lambda
secara langsung, atau dengan menggunakan DSL entryProvider.
Membuat fungsi Penyedia Entri secara langsung
Anda biasanya membuat fungsi Penyedia Entri menggunakan pernyataan when, dengan cabang untuk setiap kunci Anda.
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") } } } }
Menggunakan DSL entryProvider
DSL entryProvider dapat menyederhanakan fungsi lambda Anda dengan menghindari kebutuhan
untuk menguji setiap jenis kunci, dan membuat NavEntry untuk setiap jenis kunci.
Gunakan fungsi builder entryProvider untuk melakukannya. Fungsi ini juga menyertakan perilaku penggantian default (menampilkan error) jika kunci tidak ditemukan.
entryProvider = entryProvider { entry<ProductList> { Text("Product List") } entry<ProductDetail>( metadata = mapOf("extraDataKey" to "extraDataValue") ) { key -> Text("Product ${key.id} ") } }
Perhatikan hal berikut dari cuplikan:
entrydigunakan untuk menentukanNavEntrydengan jenis dan konten composable yang diberikanentrymenerima parametermetadatauntuk menetapkanNavEntry.metadata
Menampilkan data sebelumnya
Data sebelumnya mewakili status navigasi aplikasi Anda. Setiap kali data sebelumnya
berubah, UI aplikasi harus mencerminkan status data sebelumnya yang baru. Di Navigation 3, NavDisplay mengamati data sebelumnya dan mengupdate UI-nya. Buat
dengan parameter berikut:
- Data sebelumnya - ini harus berjenis
SnapshotStateList<T>, denganTadalah jenis kunci data sebelumnya. Ini adalahListyang dapat diamati sehingga memicu rekomposisiNavDisplaysaat berubah. entryProvideruntuk mengonversi kunci di data sebelumnya menjadi objekNavEntry.- Jika ingin, berikan lambda ke parameter
onBack. Callback ini dipanggil saat pengguna memicu peristiwa kembali.
Contoh berikut menunjukkan cara membuat 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") } } } ) }
Secara default, NavDisplay menampilkan NavEntry teratas di data sebelumnya dalam
tata letak panel tunggal. Rekaman berikut menunjukkan aplikasi ini berjalan:
NavDisplay dengan dua tujuan.Siklus proses tujuan
NavDisplay menggunakan LifecycleOwner kustom untuk membatasi status siklus proses
NavEntry berdasarkan batasan tingkat Scene dan batasan tingkat
Entri.
Untuk mengetahui informasi selengkapnya tentang siklus proses di Compose, lihat Siklus proses di Jetpack Compose.
Batasan siklus proses tingkat scene
NavDisplay mengelola siklus proses Scene yang aktif. Batas tingkat adegan ditentukan sebagai berikut:
Untuk adegan non-overlay:
RESUMED: Hanya diizinkan saat transisi scene telah selesai dan tidak ada scene overlay aktif yang ditampilkan di atasnya.STARTED: Dibatasi padaSTARTEDsaat transisi tampilan, seperti saat menavigasi maju atau mundur, atau saat ditutupi oleh overlay.
Untuk scene overlay, seperti dialog atau panel bawah:
RESUMED: Hanya diizinkan untuk scene overlay paling atas yang saat ini aktif.STARTED: Dibatasi padaSTARTEDuntuk setiap scene overlay pokok yang dicakup oleh overlay yang lebih baru.
Status siklus proses tingkat entri
Library mengelola status siklus proses maksimum setiap NavEntry
berdasarkan keberadaannya di data sebelumnya:
RESUMED: Jika entri ada di data sebelumnya saat ini, siklus prosesnya diizinkan untuk naik hinggaRESUMED(tergantung pada batas tingkat tampilan).CREATED: Jika entri tidak lagi berada di data sebelumnya, seperti saat entri di-pop, tetapi masih dirender di layar saat animasi keluar, library akan membatasi siklus prosesnya secara ketat diCREATED. Batas ini memastikan bahwa entri latar belakang atau keluar berhenti menjalankan pekerjaan aktif seperti mengumpulkan flow atau meluncurkan coroutine yang terikat ke statusRESUMEDatauSTARTEDsaat menyelesaikan transisi keluar.
Cara penggabungannya
Misalnya, status siklus proses akhir NavEntry diselesaikan sebagai berikut:
| Skenario | Batas Tingkat Adegan | Batas Tingkat Pemula | Batas Efektif |
|---|---|---|---|
| Entri aktif, layar tetap (tanpa transisi atau overlay) | RESUMED |
RESUMED |
RESUMED |
| Entri aktif, selama transisi (menavigasi ke atau dari) | STARTED |
RESUMED |
STARTED |
| Entri aktif, tercakup oleh overlay (misalnya, Dialog terbuka) | STARTED |
RESUMED |
STARTED |
| Entri yang dikeluarkan, animasi keluar | STARTED atau RESUMED |
CREATED |
CREATED |
Menggabungkan semuanya
Diagram berikut menunjukkan cara data mengalir di antara berbagai objek di Navigation 3:
Peristiwa navigasi memulai perubahan. Kunci ditambahkan atau dihapus dari data sebelumnya sebagai respons terhadap interaksi pengguna.
Perubahan status data sebelumnya memicu pengambilan konten.
NavDisplay(composable yang merender data sebelumnya) mengamati data sebelumnya. Dalam konfigurasi defaultnya, class ini menampilkan entri data sebelumnya teratas dalam tata letak panel tunggal. Saat kunci teratas pada data sebelumnya berubah,NavDisplayakan menggunakan kunci ini untuk meminta konten yang sesuai dari penyedia entri.Penyedia entri menyediakan konten. Penyedia entri adalah fungsi yang me-resolve kunci ke
NavEntry. Setelah menerima kunci dariNavDisplay, penyedia entri memberikanNavEntryterkait, yang berisi kunci dan konten.Konten ditampilkan.
NavDisplaymenerimaNavEntrydan menampilkan konten.