Meneruskan data antar-tujuan

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:

  1. Di Navigation Editor, klik tujuan yang menerima argumen.
  2. Di panel Attributes, klik Add (+).
  3. Di jendela Tambahkan Link Argumen yang muncul, masukkan nama argumen, jenis argumen, apakah argumennya dapat diubah ke null, dan nilai default, jika perlu.
  4. Klik Tambahkan. Perhatikan bahwa argumen akan muncul dalam daftar Arguments di panel Attributes.
  5. 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.
  6. 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 menggunakan app: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.

Untuk menambahkan Safe Args ke project Anda, sertakan build.gradle berikut ke file classpath tingkat teratas Anda:

Groovy

buildscript {
    repositories {
        google()
    }
    dependencies {
        def nav_version = "2.8.4"
        classpath "androidx.navigation:navigation-safe-args-gradle-plugin:$nav_version"
    }
}

Kotlin

buildscript {
    repositories {
        google()
    }
    dependencies {
        val nav_version = "2.8.4"
        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:

Groovy

plugins {
  id 'androidx.navigation.safeargs'
}

Kotlin

plugins {
    id("androidx.navigation.safeargs")
}

Atau, untuk menghasilkan kode Kotlin yang sesuai bagi modul khusus Kotlin, tambahkan:

Groovy

plugins {
  id 'androidx.navigation.safeargs.kotlin'
}

Kotlin

plugins {
    id("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 "Directions". Misalnya, jika tujuan awalnya adalah fragmen yang bernama SpecifyAmountFragment, class yang dihasilkan akan disebut SpecifyAmountFragmentDirections.

    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 nama ConfirmationAction. Jika tindakan berisi argumen tanpa defaultValue, 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 disebut ConfirmationFragmentArgs. Gunakan metode fromBundle() 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:

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.

Codelab

Video