Navigation memungkinkan Anda melampirkan data ke operasi navigasi dengan menentukan argumen untuk tujuan. Misalnya, tujuan profil pengguna mungkin mengambil argumen ID pengguna untuk menentukan pengguna yang akan ditampilkan.
Secara umum, sebaiknya Anda memilih untuk hanya meneruskan sesedikit mungkin data
antartujuan. Misalnya, Anda harus meneruskan kunci untuk mengambil objek
daripada meneruskan objek itu sendiri, karena ukuran total ruang untuk semua status
yang disimpan di Android terbatas. Jika Anda perlu meneruskan data dalam jumlah besar, gunakan
ViewModel
seperti yang dijelaskan dalam
ringkasan ViewModel.
Menentukan argumen tujuan
Untuk meneruskan data antartujuan, tentukan argumen terlebih dahulu dengan menambahkannya ke tujuan yang menerimanya dengan mengikuti langkah-langkah berikut:
- Di Navigation Editor, klik tujuan yang menerima argumen.
- Di panel Attributes, klik Add (+).
- Di jendela Tambahkan Link Argumen yang muncul, masukkan nama argumen, jenis argumen, apakah argumennya dapat diubah ke null, dan nilai default, jika perlu.
- Klik Tambahkan. Perhatikan bahwa argumen akan muncul dalam daftar Arguments di panel Attributes.
- Selanjutnya, klik tindakan yang sesuai dan membawa Anda ke tujuan ini. Di panel Attributes, Anda akan melihat argumen yang baru ditambahkan di bagian Argument Default Values.
Anda juga dapat melihat bahwa argumen ditambahkan dalam XML. Klik tab Text untuk beralih ke tampilan XML, dan perhatikan bahwa argumen Anda telah ditambahkan ke tujuan yang menerima argumen. Contohnya ditampilkan sebagai berikut:
<fragment android:id="@+id/myFragment" > <argument android:name="myArg" app:argType="integer" android:defaultValue="0" /> </fragment>
Jenis argumen yang didukung
Library Navigasi mendukung jenis argumen berikut:
Jenis | Sintaksis app:argType | Dukungan untuk nilai default | Ditangani oleh rute | Nullable |
---|---|---|---|---|
Bilangan Bulat | app:argType="integer" | Ya | Ya | Tidak |
Float | app:argType="float" | Ya | Ya | Tidak |
Panjang | app:argType="long" | Ya - Nilai default harus selalu diakhiri dengan akhiran 'L' (misalnya, '123L'). | Ya | Tidak |
Boolean | app:argType="boolean" | Ya - "true" atau "false" | Ya | Tidak |
String | app:argType="string" | Ya | Ya | Ya |
Referensi Resource | app:argType="reference" | Ya - Nilai default harus dalam bentuk "@resourceType/resourceName" (misalnya "@style/myCustomStyle") atau"0" | Ya | Tidak |
Parcelable Kustom | app:argType="<type>", yang mana <type> adalah nama class Parcelable yang sepenuhnya memenuhi syarat |
Mendukung nilai default "@null". Tidak mendukung nilai default lainnya. | Tidak | Ya |
Serializable Kustom | app:argType="<type>", yang mana <type> adalah nama class Serializable yang sepenuhnya memenuhi syarat |
Mendukung nilai default "@null". Tidak mendukung nilai default lainnya. | Tidak | Ya |
Enum Kustom | app:argType="<type>", yang mana <type> adalah nama enum yang sepenuhnya memenuhi syarat | Ya - Nilai default harus sama dengan nama yang tidak memenuhi syarat (misalnya "SUCCESS" agar sama dengan MyEnum.SUCCESS). | Tidak | Tidak |
Jika jenis argumen mendukung nilai null, Anda dapat mendeklarasikan nilai default
null menggunakan android:defaultValue="@null"
.
Rute, deep link, dan URI dengan argumennya dapat diuraikan dari string. Jenis data kustom tidak mungkin digunakan, misalnya Parcelable dan Serializable, seperti yang terlihat dalam tabel sebelumnya. Untuk meneruskan data kompleks kustom, simpan data di tempat lain seperti ViewModel atau database dan hanya teruskan ID saat bernavigasi; lalu ambil data di lokasi baru setelah navigasi selesai.
Saat Anda memilih salah satu jenis kustom, dialog Select Class akan muncul dan meminta Anda memilih class yang sesuai untuk jenis tersebut. Tab Project memungkinkan Anda memilih class dari project saat ini.
Anda dapat memilih <jenis yang ditentukan> agar library Navigasi menentukan jenis menurut nilai yang diberikan.
Anda dapat memeriksa Array untuk menunjukkan bahwa argumen harus berupa array nilai Jenis yang dipilih. Perhatikan hal berikut:
- Array enum dan array referensi resource tidak didukung.
- Array mendukung nilai nullable, terlepas dari dukungan untuk nilai
nullable dari jenis dasar. Misalnya, penggunaan
app:argType="integer[]"
memungkinkan Anda menggunakanapp:nullable="true"
untuk menunjukkan bahwa meneruskan array null dapat diterima. - Array mendukung satu nilai default, "@null". Array tidak mendukung nilai default lainnya.
Mengganti argumen tujuan dalam suatu tindakan
Argumen tingkat tujuan dan nilai default digunakan oleh semua tindakan yang mengarah ke tujuan. Jika diperlukan, Anda dapat mengganti nilai default argumen (atau menetapkan nilai default jika belum ada) dengan menetapkan argumen di level tindakan. Argumen ini harus memiliki nama dan jenis yang sama seperti argumen yang dideklarasikan di tujuan.
XML berikut mendeklarasikan tindakan dengan argumen yang menggantikan argumen tingkat tujuan dari contoh sebelumnya:
<action android:id="@+id/startMyFragment"
app:destination="@+id/myFragment">
<argument
android:name="myArg"
app:argType="integer"
android:defaultValue="1" />
</action>
Menggunakan Safe Args untuk meneruskan data dengan keamanan jenis
Komponen Navigation memiliki plugin Gradle bernama Safe Args yang menghasilkan class builder dan objek sederhana untuk navigasi dengan keamanan jenis dan akses ke argumen terkait. Safe Args sangat disarankan untuk menavigasi dan meneruskan data, karena memastikan keamanan jenis.
Jika tidak menggunakan Gradle, Anda tidak dapat menggunakan plugin Safe Args. Dalam kasus ini, Anda dapat menggunakan Bundle untuk langsung meneruskan data.
如需将 Safe Args 添加到您的项目,请在顶层 build.gradle
文件中包含以下 classpath
:
Groovy
buildscript { repositories { google() } dependencies { def nav_version = "2.8.0" classpath "androidx.navigation:navigation-safe-args-gradle-plugin:$nav_version" } }
Kotlin
buildscript { repositories { google() } dependencies { val nav_version = "2.8.0" classpath("androidx.navigation:navigation-safe-args-gradle-plugin:$nav_version") } }
您还必须应用以下两个可用插件之一。
如需生成适用于 Java 模块或 Java 和 Kotlin 混合模块的 Java 语言代码,请将以下行添加到应用或模块的 build.gradle
文件中:
Groovy
plugins { id 'androidx.navigation.safeargs' }
Kotlin
plugins { id("androidx.navigation.safeargs") }
此外,如需生成仅适用于 Kotlin 模块的 Kotlin 语言代码,请添加以下行:
Groovy
plugins { id 'androidx.navigation.safeargs.kotlin' }
Kotlin
plugins { id("androidx.navigation.safeargs.kotlin") }
根据迁移到 AndroidX 文档,您的 gradle.properties
文件中必须具有 android.useAndroidX=true
。
Setelah mengaktifkan Safe Args, kode yang dihasilkan berisi class dan metode dengan keamanan jenis berikut untuk setiap tindakan serta setiap tujuan pengiriman dan penerimaan.
Class dibuat untuk setiap tujuan tempat asal tindakan. Nama class ini adalah nama tujuan awal, ditambah dengan kata "Directions". Misalnya, jika tujuan awalnya adalah fragmen yang bernama
SpecifyAmountFragment
, class yang dihasilkan akan disebutSpecifyAmountFragmentDirections
.Class ini memiliki metode untuk setiap tindakan yang ditentukan di tujuan awal.
Untuk setiap tindakan yang digunakan untuk meneruskan argumen, class dalam yang namanya didasarkan pada tindakan akan dibuat. Misalnya, jika tindakan ini disebut
confirmationAction,
, class akan diberi namaConfirmationAction
. Jika tindakan berisi argumen tanpadefaultValue
, Anda menggunakan class tindakan terkait untuk menetapkan nilai argumen.Class dibuat untuk tujuan penerima. Nama class ini adalah nama tujuan, ditambah dengan kata "Args". Misalnya, jika fragmen tujuan diberi nama
ConfirmationFragment,
, class yang dihasilkan disebutConfirmationFragmentArgs
. Gunakan metodefromBundle()
class ini untuk mengambil argumen.
Contoh berikut menunjukkan cara menggunakan metode ini untuk menetapkan argumen dan
meneruskannya ke metode
navigate()
:
Kotlin
override fun onClick(v: View) { val amountTv: EditText = view!!.findViewById(R.id.editTextAmount) val amount = amountTv.text.toString().toInt() val action = SpecifyAmountFragmentDirections.confirmationAction(amount) v.findNavController().navigate(action) }
Java
@Override public void onClick(View view) { EditText amountTv = (EditText) getView().findViewById(R.id.editTextAmount); int amount = Integer.parseInt(amountTv.getText().toString()); ConfirmationAction action = SpecifyAmountFragmentDirections.confirmationAction(); action.setAmount(amount); Navigation.findNavController(view).navigate(action); }
Dalam kode untuk tujuan penerima, gunakan metode getArguments()
untuk mengambil paket dan menggunakan kontennya. Saat menggunakan dependensi
-ktx
, pengguna Kotlin juga dapat menggunakan delegasi properti by navArgs()
untuk mengakses argumen.
Kotlin
val args: ConfirmationFragmentArgs by navArgs() override fun onViewCreated(view: View, savedInstanceState: Bundle?) { val tv: TextView = view.findViewById(R.id.textViewAmount) val amount = args.amount tv.text = amount.toString() }
Java
@Override public void onViewCreated(View view, @Nullable Bundle savedInstanceState) { TextView tv = view.findViewById(R.id.textViewAmount); int amount = ConfirmationFragmentArgs.fromBundle(getArguments()).getAmount(); tv.setText(amount + ""); }
Menggunakan Safe Args dengan tindakan global
Saat menggunakan Safe Arg
dengan tindakan global,
Anda harus memberikan nilai android:id
untuk elemen <navigation>
root Anda, seperti
yang ditunjukkan dalam contoh berikut:
<?xml version="1.0" encoding="utf-8"?> <navigation xmlns:app="http://schemas.android.com/apk/res-auto" xmlns:tools="http://schemas.android.com/tools" xmlns:android="http://schemas.android.com/apk/res/android" android:id="@+id/main_nav" app:startDestination="@id/mainFragment"> ... </navigation>
Navigasi menghasilkan class Directions
untuk elemen <navigation>
yang
didasarkan pada nilai android:id
. Misalnya, jika Anda memiliki elemen
<navigation>
dengan android:id=@+id/main_nav
, class yang dihasilkan akan disebut
MainNavDirections
. Semua tujuan dalam elemen <navigation>
telah
menghasilkan metode untuk mengakses semua tindakan global yang terkait menggunakan
metode yang sama seperti yang dijelaskan di bagian sebelumnya.
Meneruskan data antar-tujuan dengan objek Bundle
Jika tidak menggunakan Gradle, Anda tetap dapat meneruskan argumen antartujuan
menggunakan objek Bundle
. Buat objek Bundle
dan teruskan ke tujuan
menggunakan navigate()
, seperti pada contoh berikut:
Kotlin
val bundle = bundleOf("amount" to amount) view.findNavController().navigate(R.id.confirmationAction, bundle)
Java
Bundle bundle = new Bundle(); bundle.putString("amount", amount); Navigation.findNavController(view).navigate(R.id.confirmationAction, bundle);
Dalam kode tujuan penerima Anda, gunakan metode getArguments()
untuk
mengambil Bundle
dan menggunakan kontennya:
Kotlin
val tv = view.findViewById<TextView>(R.id.textViewAmount) tv.text = arguments?.getString("amount")
Java
TextView tv = view.findViewById(R.id.textViewAmount); tv.setText(getArguments().getString("amount"));
Meneruskan data ke tujuan awal
Anda dapat meneruskan data ke tujuan awal aplikasi. Pertama, Anda harus
membuat Bundle
yang menyimpan data secara eksplisit. Selanjutnya,
gunakan salah satu pendekatan berikut untuk meneruskan Bundle
ke tujuan awal:
- Jika Anda membuat
NavHost
secara terprogram, panggilNavHostFragment.create(R.navigation.graph, args)
, denganargs
adalahBundle
yang menyimpan data Anda. - Jika tidak, Anda dapat menetapkan argumen tujuan awal
dengan
memanggil salah satu overload
NavController.setGraph()
berikut:- Menggunakan ID grafik:
navController.setGraph(R.navigation.graph, args)
- Menggunakan grafik itu sendiri:
navController.setGraph(navGraph, args)
- Menggunakan ID grafik:
Untuk mengambil data di tujuan awal, panggil
Fragment.getArguments()
.
Pertimbangan ProGuard
Jika Anda menyingkat kode, Anda perlu mencegah
nama class Parcelable
, Serializable
, dan Enum
agar tidak di-obfuscate sebagai bagian dari
proses minifikasi. Anda dapat melakukannya dengan salah satu dari dua cara berikut:
- Menggunakan anotasi @Keep.
- Menggunakan aturan keepnames.
Subbagian berikut menguraikan pendekatan ini.
Menggunakan anotasi @Keep
Contoh berikut menambahkan anotasi @Keep
ke definisi class model:
Kotlin
@Keep class ParcelableArg : Parcelable { ... } @Keep class SerializableArg : Serializable { ... } @Keep enum class EnumArg { ... }
Java
@Keep public class ParcelableArg implements Parcelable { ... } @Keep public class SerializableArg implements Serializable { ... } @Keep public enum EnumArg { ... }
Menggunakan aturan keepnames
Anda juga dapat menambahkan aturan keepnames
untuk file proguard-rules.pro
, seperti yang ditunjukkan
pada contoh berikut:
proguard-rules.pro
...
-keepnames class com.path.to.your.ParcelableArg
-keepnames class com.path.to.your.SerializableArg
-keepnames class com.path.to.your.EnumArg
...
Referensi lainnya
Untuk mempelajari navigasi lebih lanjut, lihat referensi tambahan berikut.