การนำทางช่วยให้คุณแนบข้อมูลไปกับการดำเนินการนำทางด้วยการกำหนดอาร์กิวเมนต์ สำหรับปลายทาง เช่น ปลายทางโปรไฟล์ผู้ใช้อาจใช้รหัสผู้ใช้ เพื่อกำหนดผู้ใช้ที่จะแสดง
โดยทั่วไปแล้ว คุณควรส่งข้อมูลในปริมาณน้อยที่สุด
ระหว่างปลายทาง เช่น คุณควรส่งคีย์เพื่อเรียกข้อมูลออบเจ็กต์
แทนที่จะส่งตัวอ็อบเจกต์ เพราะเป็นพื้นที่รวมสำหรับสถานะที่บันทึกไว้ทั้งหมด
ถูกจำกัดใน Android ถ้าคุณต้องการส่งผ่านข้อมูลปริมาณมาก ให้ใช้
ViewModel
ตามที่อธิบายไว้ใน
ดูภาพรวมของโมเดล
กำหนดอาร์กิวเมนต์ปลายทาง
ในการส่งข้อมูลระหว่างปลายทาง ให้กำหนดอาร์กิวเมนต์โดยเพิ่มลงใน ปลายทางที่ได้รับ โดยทำตามขั้นตอนต่อไปนี้
- ในตัวแก้ไขการนำทาง ให้คลิกปลายทางที่รับอาร์กิวเมนต์
- ในแผงแอตทริบิวต์ ให้คลิกเพิ่ม (+)
- ในหน้าต่างเพิ่มลิงก์อาร์กิวเมนต์ที่ปรากฏขึ้น ให้ป้อนชื่ออาร์กิวเมนต์ ประเภทอาร์กิวเมนต์ ว่าอาร์กิวเมนต์เป็นค่าว่างหรือไม่ และค่าเริ่มต้น ที่จำเป็น
- คลิกเพิ่ม โปรดสังเกตว่าขณะนี้อาร์กิวเมนต์จะปรากฏในอาร์กิวเมนต์ ในแผงแอตทริบิวต์
- จากนั้นคลิกการดำเนินการที่เกี่ยวข้องซึ่งจะนำคุณไปยังปลายทางนี้ ในแผงแอตทริบิวต์ คุณจะเห็นอาร์กิวเมนต์ที่เพิ่มใหม่ ในส่วนค่าเริ่มต้นของอาร์กิวเมนต์
คุณยังจะเห็นว่ามีการเพิ่มอาร์กิวเมนต์ใน XML ด้วย คลิกแท็บข้อความ สลับเป็นมุมมอง XML และสังเกตว่ามีการเพิ่มอาร์กิวเมนต์ลงใน ปลายทางที่รับอาร์กิวเมนต์ ตัวอย่างได้แก่
<fragment android:id="@+id/myFragment" > <argument android:name="myArg" app:argType="integer" android:defaultValue="0" /> </fragment>
ประเภทอาร์กิวเมนต์ที่รองรับ
ไลบรารีการนำทางสนับสนุนประเภทอาร์กิวเมนต์ต่อไปนี้
ประเภท | ไวยากรณ์ app:argType | การรองรับค่าเริ่มต้น | จัดการโดยเส้นทาง | เว้นว่างได้ |
---|---|---|---|---|
จำนวนเต็ม | app:ARPType="integer" | ใช่ | ได้ | ไม่ |
ล่องลอย | app:argType="Flo" | ใช่ | ได้ | ไม่ |
ยาว | app:ARPType="long" | ใช่ - ค่าเริ่มต้นต้องลงท้ายด้วย "L" เสมอ คำต่อท้าย (เช่น "123L") | ใช่ | ไม่ |
บูลีน | app:ARPType="boolean" | ใช่ - "จริง" หรือ "เท็จ" | ใช่ | ไม่ |
สตริง | app:argType="string" | ใช่ | ได้ | ใช่ |
การอ้างอิงทรัพยากร | app:argType="reference" | ใช่ ค่าเริ่มต้นต้องอยู่ในรูปแบบ "@resourceType/resourceName" (เช่น "@style/myCustomStyle") หรือ "0" | ใช่ | ไม่ |
พาร์เซลที่กำหนดเอง | app:argType="<type>" โดยที่ <type> คือชื่อคลาสที่มีคุณสมบัติครบถ้วนของ Parcelable |
รองรับค่าเริ่มต้นเป็น "@null" ไม่รองรับค่าเริ่มต้นอื่นๆ | ไม่ | ใช่ |
ซีเรียลได้แบบกำหนดเอง | app:argType="<type>" โดยที่ <type> คือชื่อคลาสที่มีคุณสมบัติครบถ้วนของ Serializable |
รองรับค่าเริ่มต้นเป็น "@null" ไม่รองรับค่าเริ่มต้นอื่นๆ | ไม่ | ใช่ |
Enum ที่กำหนดเอง | app:argType="<type>" โดยที่ <type> คือชื่อที่มีคุณสมบัติครบถ้วนของ enum | ใช่ - ค่าเริ่มต้นต้องตรงกับชื่อที่ไม่เข้าเกณฑ์ (เช่น "สำเร็จ" เพื่อให้ตรงกับ MyEnum.SUCCESS) | ไม่ | ไม่ |
ถ้าประเภทอาร์กิวเมนต์รองรับค่า Null คุณจะประกาศค่าเริ่มต้นได้
null โดยใช้ android:defaultValue="@null"
แยกวิเคราะห์เส้นทาง, Deep Link และ URI ที่มีอาร์กิวเมนต์จากสตริงได้ คุณไม่สามารถใช้ประเภทข้อมูลที่กำหนดเอง เช่น พาร์เซล และ ทำให้ต่อเนื่องได้ตามที่เห็นในตารางก่อนหน้านี้ หากต้องการส่งต่อข้อมูลที่ซับซ้อนที่กำหนดเอง ให้เก็บข้อมูลนั้นไว้ที่อื่น เช่น ViewModel หรือฐานข้อมูลและส่งผ่านตัวระบุขณะนำทางเท่านั้น จากนั้นดึงข้อมูลในตำแหน่งใหม่หลังจากที่การนำทางสิ้นสุดลง
เมื่อเลือกประเภทที่กำหนดเอง กล่องโต้ตอบเลือกชั้นเรียนจะปรากฏขึ้น และ ระบบจะให้คุณเลือกคลาสที่เกี่ยวข้องกับประเภทนั้นๆ แท็บโปรเจ็กต์ ให้คุณเลือกชั้นเรียนจากโปรเจ็กต์ปัจจุบัน
คุณสามารถเลือก <inferred type> ให้มีไลบรารีการนำทาง กำหนดประเภทตามค่าที่ระบุ
คุณสามารถตรวจสอบ Array เพื่อระบุว่าอาร์กิวเมนต์ควรเป็นอาร์เรย์ของ ค่า Type ที่เลือกไว้ ข้อควรทราบ
- ระบบไม่รองรับอาร์เรย์ของ enum และอาร์เรย์ของการอ้างอิงทรัพยากร
- อาร์เรย์รองรับค่า Nullable โดยไม่คำนึงถึงการรองรับค่า Null
ของประเภทที่สำคัญ ตัวอย่างเช่น การใช้
app:argType="integer[]"
ช่วยให้คุณใช้app:nullable="true"
เพื่อ ระบุว่าการส่งผ่านอาร์เรย์ Null นั้นเป็นที่ยอมรับได้ - อาร์เรย์รองรับค่าเริ่มต้นค่าเดียว ซึ่งก็คือ "@null" อาร์เรย์ไม่รองรับรายการใดเลย ค่าเริ่มต้นอื่นๆ
ลบล้างอาร์กิวเมนต์ปลายทางในการดำเนินการ
ระบบจะใช้อาร์กิวเมนต์ระดับปลายทางและค่าเริ่มต้นในการดําเนินการทั้งหมดที่ นำทางไปยังจุดหมาย หากจำเป็น คุณสามารถลบล้างค่าเริ่มต้นของ (หรือกำหนดอาร์กิวเมนต์หากยังไม่มี) โดยกำหนดอาร์กิวเมนต์ที่ ระดับการดำเนินการ อาร์กิวเมนต์นี้ต้องมีชื่อและประเภทเดียวกับอาร์กิวเมนต์ ที่ประกาศไว้ในปลายทาง
XML ต่อไปนี้จะประกาศการดำเนินการที่มีอาร์กิวเมนต์ที่ลบล้าง อาร์กิวเมนต์ระดับปลายทางจากตัวอย่างก่อนหน้านี้:
<action android:id="@+id/startMyFragment"
app:destination="@+id/myFragment">
<argument
android:name="myArg"
app:argType="integer"
android:defaultValue="1" />
</action>
ใช้ Args ที่ปลอดภัยเพื่อส่งผ่านข้อมูลด้วยประเภทความปลอดภัย
คอมโพเนนต์การนำทางมีปลั๊กอิน Gradle ชื่อ Safe Args ซึ่งสร้าง คลาสออบเจ็กต์และเครื่องมือสร้างแบบง่ายๆ สำหรับการนำทางที่ปลอดภัยชนิดและสิทธิ์เข้าถึง อาร์กิวเมนต์ที่เกี่ยวข้อง ขอแนะนำอย่างยิ่งให้ใช้ Args ที่ปลอดภัยสำหรับการนำทางและ การส่งข้อมูล เนื่องจากช่วยรับประกันความปลอดภัยในประเภท
หากไม่ได้ใช้ Gradle คุณจะใช้ Gradle ไม่ได้ ปลั๊กอิน Args ในกรณีเหล่านี้ คุณใช้แพ็กเกจได้โดยตรง ส่งข้อมูล
หากต้องการเพิ่ม Safe Args ลงในโปรเจ็กต์ ให้ใส่ classpath
ต่อไปนี้ในไฟล์ build.gradle
ระดับบนสุด
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") } }
นอกจากนี้ คุณยังต้องใช้ปลั๊กอิน 1 ใน 2 รายการที่มีให้
หากต้องการสร้างโค้ดภาษา Java ที่เหมาะสมกับโมดูล Java หรือโมดูลแบบผสม Java และ Kotlin ให้เพิ่มบรรทัดนี้ลงในไฟล์ 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") }
คุณต้องมี android.useAndroidX=true
ในไฟล์ gradle.properties
ตามหัวข้อการย้ายข้อมูลไปยัง AndroidX
หลังจากเปิดใช้ Safe Args แล้ว โค้ดที่สร้างขึ้นจะมีข้อมูลต่อไปนี้ ประเภทและวิธีการที่ปลอดภัยสำหรับการดำเนินการแต่ละอย่าง รวมถึงการส่งและ ปลายทางที่จะรับ
ระบบจะสร้างคลาสสำหรับปลายทางแต่ละแห่งที่การกระทำเกิดขึ้น ชื่อ ของคลาสนี้เป็นชื่อของปลายทางต้นทางที่ต่อท้ายด้วย คำว่า "เส้นทาง" เช่น หากปลายทางต้นทางเป็นส่วนย่อย ที่ชื่อ
SpecifyAmountFragment
คลาสที่สร้างขึ้นจะเรียกว่าSpecifyAmountFragmentDirections
คลาสนี้มีเมธอดสำหรับแต่ละการทำงานที่กำหนดไว้ในแท็กเริ่มต้น ปลายทาง
สำหรับการดำเนินการแต่ละรายการที่ใช้ส่งผ่านอาร์กิวเมนต์ คลาสภายในจะถูกสร้างขึ้นโดยมี ชื่อจะขึ้นอยู่กับการดำเนินการนั้นๆ เช่น หากมีการเรียกการดำเนินการ
confirmationAction,
ชั้นเรียนมีชื่อว่าConfirmationAction
หาก มีอาร์กิวเมนต์ที่ไม่มีdefaultValue
ให้ใช้ คลาสการดำเนินการที่เชื่อมโยงเพื่อกำหนดค่าของอาร์กิวเมนต์ระบบจะสร้างคลาสสำหรับปลายทางการรับ ชื่อของชั้นเรียนนี้คือ ชื่อของปลายทางต่อท้ายด้วยคำว่า "Args" ตัวอย่างเช่น หาก ส่วนย่อยปลายทางชื่อ
ConfirmationFragment,
ที่สร้าง ชื่อคลาสคือConfirmationFragmentArgs
ใช้fromBundle()
ของชั้นเรียนนี้ เพื่อเรียกอาร์กิวเมนต์
ตัวอย่างต่อไปนี้จะแสดงวิธีใช้วิธีการเหล่านี้เพื่อตั้งค่าอาร์กิวเมนต์และ
ส่งไปยัง 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); }
ในโค้ดสำหรับปลายทางการรับ ให้ใช้เมธอด getArguments()
เพื่อเรียกแพ็กเกจและใช้เนื้อหาของแพ็กเกจ เมื่อใช้ทรัพยากร Dependency -ktx
ผู้ใช้ Kotlin ยังใช้ผู้ได้รับมอบสิทธิ์พร็อพเพอร์ตี้ by navArgs()
เพื่อเข้าถึงได้ด้วย
อาร์กิวเมนต์
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 + ""); }
ใช้อาร์กิวเมนต์ที่ปลอดภัยกับการดําเนินการส่วนกลาง
เมื่อใช้ Safe Args กับ
การดำเนินการส่วนกลาง
คุณต้องระบุค่า android:id
สำหรับองค์ประกอบ <navigation>
รากของคุณ เป็น
ที่แสดงในตัวอย่างต่อไปนี้
<?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>
การนำทางจะสร้างคลาส Directions
สำหรับองค์ประกอบ <navigation>
ที่
ที่อิงตามค่า android:id
เช่น หากคุณมี <navigation>
ที่มี android:id=@+id/main_nav
คลาสที่สร้างขึ้นนี้จะเรียกว่า
MainNavDirections
ปลายทางทั้งหมดภายในองค์ประกอบ <navigation>
มี
ที่สร้างขึ้นสำหรับการเข้าถึงการทำงานส่วนกลางที่เกี่ยวข้องทั้งหมดโดยใช้
ตามที่อธิบายไว้ในส่วนก่อนหน้านี้
ส่งข้อมูลระหว่างปลายทางด้วยออบเจ็กต์ Bundle
หากไม่ได้ใช้ Gradle คุณจะยังคงส่งอาร์กิวเมนต์ระหว่างปลายทางได้โดย
โดยใช้ออบเจ็กต์ Bundle
รายการ สร้างออบเจ็กต์ Bundle
และส่งไปยังปลายทาง
โดยใช้ navigate()
ตามตัวอย่างต่อไปนี้
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);
ในโค้ดของปลายทางการรับ ให้ใช้เมธอด getArguments()
เพื่อ
เรียก Bundle
และใช้เนื้อหาของ:
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"));
ส่งผ่านข้อมูลไปยังปลายทางเริ่มต้น
คุณส่งข้อมูลไปยังปลายทางเริ่มต้นของแอปได้ ก่อนอื่นคุณต้อง
สร้าง Bundle
ที่เก็บรักษาข้อมูล ต่อไป ให้ใช้รายการใดรายการหนึ่งต่อไปนี้
วิธีส่ง Bundle
ไปยังปลายทางเริ่มต้น
- หากคุณสร้าง
NavHost
แบบเป็นโปรแกรม ให้เรียกใช้NavHostFragment.create(R.navigation.graph, args)
, โดยที่args
คือBundle
ที่เก็บข้อมูลของคุณ - หรือตั้งค่าอาร์กิวเมนต์ปลายทางเริ่มต้นโดยเรียกใช้หนึ่งใน
โอเวอร์โหลดของ
NavController.setGraph()
ต่อไปนี้:- ใช้รหัสของกราฟ:
navController.setGraph(R.navigation.graph, args)
- ใช้กราฟนี้
navController.setGraph(navGraph, args)
- ใช้รหัสของกราฟ:
หากต้องการดึงข้อมูลในปลายทางเริ่มต้น ให้เรียกใช้
Fragment.getArguments()
ข้อควรพิจารณาเกี่ยวกับ ProGuard
หากคุณลดขนาดโค้ด คุณต้องป้องกันParcelable
ไม่ให้ปรับชื่อคลาส Serializable
และ Enum
ให้ยากต่อการอ่าน (Obfuscate) เพื่อเป็นส่วนหนึ่งของ
กระบวนการลดขนาด คุณสามารถทำได้ด้วยวิธีใดวิธีหนึ่งใน 2 วิธีต่อไปนี้
- ใช้คำอธิบายประกอบ @Keep
- ใช้กฎ Keepnames
ส่วนย่อยต่อไปนี้จะแสดงแนวทางเหล่านี้
ใช้คำอธิบายประกอบ @Keep
ตัวอย่างต่อไปนี้จะเพิ่มคำอธิบายประกอบ @Keep
ลงในโมเดลคำจำกัดความคลาส
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 { ... }
ใช้กฎ Keepname
คุณยังเพิ่มกฎ keepnames
ข้อลงในไฟล์ proguard-rules.pro
ได้ด้วยตามที่แสดงไว้
ในตัวอย่างต่อไปนี้
proguard-rules.pro
...
-keepnames class com.path.to.your.ParcelableArg
-keepnames class com.path.to.your.SerializableArg
-keepnames class com.path.to.your.EnumArg
...
แหล่งข้อมูลเพิ่มเติม
หากต้องการเรียนรู้เพิ่มเติมเกี่ยวกับการนำทาง โปรดดูข้อมูลต่อไปนี้ แหล่งข้อมูลเพิ่มเติม