Dengan Navigasi, Anda dapat 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 antar-tujuan. Misalnya, Anda harus meneruskan kunci untuk mengambil objek alih-alih meneruskan objek itu sendiri, karena ukuran total ruang untuk semua status yang disimpan di Android terbatas. Jika perlu mengirimkan data dalam jumlah besar, pertimbangkan untuk menggunakan ViewModel
seperti yang dijelaskan dalam Berbagi data antar-fragmen.
Menentukan argumen tujuan
Untuk meneruskan data antar-tujuan, tentukan argumen terlebih dahulu dengan menambahkannya ke tujuan yang menerimanya dengan mengikuti langkah-langkah berikut:
- Di Editor navigasi, klik tujuan yang menerima argumen.
- Di panel Atribut, klik Tambahkan (+).
- 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 Argumen di panel Atribut.
- Selanjutnya, klik tindakan yang sesuai yang membawa Anda ke tujuan ini. Di panel Atribut, Anda akan melihat argumen yang baru ditambahkan di bagian Nilai Default Argumen.
Anda juga dapat melihat bahwa argumen ditambahkan dalam XML. Klik tab Teks untuk beralih ke tampilan XML, dan perhatikan bahwa argumen Anda telah ditambahkan ke tujuan yang menerima argumen. Contohnya ditampilkan di bawah ini:
<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 | app:argType syntax | Mendukung nilai default? | Mendukung nilai null? |
---|---|---|---|
Bilangan Bulat | app:argType="integer" | Ya | Tidak |
Float | app:argType="float" | Ya | Tidak |
Panjang | app:argType="long" | Ya - Nilai default harus selalu diakhiri dengan akhiran 'L' (misalnya, '123L'). | Tidak |
Boolean | app:argType="boolean" | Ya - "true" atau "false" | Tidak |
String | app:argType="string" | Ya | Ya |
Referensi Resource | app:argType="reference" | Ya - Nilai default harus dalam bentuk "@resourceType/resourceName" (misalnya "@style/myCustomStyle ") atau"0" | 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. | 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. | Ya |
Enum Kustom | app:argType="<type>", yang mana <type> adalah nama enum yang sepenuhnya memenuhi syarat | Ya - Nilai default harus cocok dengan nama yang tidak memenuhi syarat (misalnya "SUCCESS" agar cocok dengan MyEnum.SUCCESS). | Tidak |
Jika jenis argumen mendukung nilai null, Anda dapat mendeklarasikan nilai default null menggunakan android:defaultValue="@null"
.
Saat Anda memilih salah satu jenis kustom, dialog Pilih 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 bahwa array enum dan array referensi resource tidak didukung. Array selalu dapat diubah ke null, terlepas dari nullability dari jenis yang mendasari. 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 di bawah mendeklarasikan tindakan dengan argumen yang menggantikan argumen tingkat tujuan dari contoh di atas:
<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 Navigasi memiliki plugin Gradle bernama Safe Args yang menghasilkan class builder dan objek sederhana untuk navigasi yang aman jenisnya dan akses ke argumen terkait. Safe Args sangat disarankan untuk menavigasi dan meneruskan data, karena memastikan keamanan jenis.
Dalam beberapa kasus, jika tidak menggunakan Gradle, misalkan, Anda tidak dapat menggunakan plugin Safe Args. Dalam kasus ini, Anda dapat menggunakan Bundle untuk langsung meneruskan data.
Untuk menambahkan Safe Args ke project Anda, sertakan build.gradle
berikut ke file classpath
tingkat teratas Anda:
buildscript { repositories { google() } dependencies { def nav_version = "2.3.2" classpath "androidx.navigation:navigation-safe-args-gradle-plugin:$nav_version" } }
Anda juga harus menerapkan salah satu dari dua plugin yang tersedia.
Untuk menghasilkan kode bahasa Java yang sesuai bagi modul Java atau modul campuran Java dan Kotlin, tambahkan baris berikut ke file build.gradle
aplikasi atau modul Anda:
apply plugin: "androidx.navigation.safeargs"
Atau, untuk menghasilkan kode Kotlin yang cocok dengan modul khusus Kotlin tambahkan:
apply plugin: "androidx.navigation.safeargs.kotlin"
Anda harus memiliki android.useAndroidX=true
dalam file gradle.properties
seperti yang dijelaskan dalam Bermigrasi ke AndroidX.
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 "Petunjuk Arah". 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 tujuan penerima Anda, gunakan metode getArguments()
untuk mengambil bundle 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 pada 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 antar-tujuan menggunakan objek Bundle
. Buat objek Bundle
dan teruskan ke tujuan menggunakan navigate()
, seperti yang ditunjukkan di bawah ini:
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 metode berikut untuk meneruskan Bundle
ke tujuan awal:
- Jika Anda membuat file
NavHost
secara terprogram, panggilNavHostFragment.create(R.navigation.graph, args)
, dengan args 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 menciutkan 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
Contoh di bawah ini 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.