ไลบรารีของ Dynamic Navigator ขยายฟังก์ชันการทำงานของ คอมโพเนนต์การนำทางของ Jetpack เพื่อทำงานกับปลายทาง ที่กำหนดไว้ใน โมดูลฟีเจอร์ ไลบรารีนี้ยังมีการติดตั้งฟีเจอร์ออนดีมานด์ที่ราบรื่น เมื่อไปยังปลายทางเหล่านี้
ตั้งค่า
หากต้องการรองรับโมดูลฟีเจอร์ ให้ใช้ทรัพยากร Dependency ต่อไปนี้ในไฟล์ build.gradle
ของโมดูลแอป
ดึงดูด
dependencies { def nav_version = "2.7.7" api "androidx.navigation:navigation-fragment-ktx:$nav_version" api "androidx.navigation:navigation-ui-ktx:$nav_version" api "androidx.navigation:navigation-dynamic-features-fragment:$nav_version" }
Kotlin
dependencies { val nav_version = "2.7.7" api("androidx.navigation:navigation-fragment-ktx:$nav_version") api("androidx.navigation:navigation-ui-ktx:$nav_version") api("androidx.navigation:navigation-dynamic-features-fragment:$nav_version") }
โปรดทราบว่าทรัพยากร Dependency อื่นๆ ของการนำทางควรใช้การกำหนดค่า API เพื่อให้พร้อมใช้งานกับโมดูลฟีเจอร์
การใช้งานพื้นฐาน
หากต้องการสนับสนุนโมดูลฟีเจอร์ โปรดเปลี่ยนอินสแตนซ์ทั้งหมดของ
NavHostFragment
ในแอปของคุณเพื่อ
androidx.navigation.dynamicfeatures.fragment.DynamicNavHostFragment
:
<androidx.fragment.app.FragmentContainerView
android:id="@+id/nav_host_fragment"
android:name="androidx.navigation.dynamicfeatures.fragment.DynamicNavHostFragment"
app:navGraph="@navigation/nav_graph"
... />
จากนั้น เพิ่มแอตทริบิวต์ app:moduleName
ลงใน <activity>
, <fragment>
หรือ
จุดหมาย <navigation>
แห่งในโมดูล com.android.dynamic-feature
กราฟการนำทางที่เชื่อมโยงกับ DynamicNavHostFragment
แอตทริบิวต์นี้จะบอกไลบรารี Dynamic Navigator ว่าปลายทาง
เป็นของโมดูลฟีเจอร์ที่มีชื่อที่คุณระบุ
<fragment
app:moduleName="myDynamicFeature"
android:id="@+id/featureFragment"
android:name="com.google.android.samples.feature.FeatureFragment"
... />
เมื่อคุณนำทางไปยังจุดหมายเหล่านี้ ไลบรารีการนำทางแบบไดนามิก ก่อนอื่นให้ตรวจสอบว่ามีการติดตั้งโมดูลฟีเจอร์หรือไม่ หากฟีเจอร์ อยู่แล้ว แอปของคุณจะนำทางไปยังปลายทางตามที่คาดไว้ หากไม่มีโมดูลนี้ แสดงว่าแอปแสดงส่วนย่อยของความคืบหน้าระดับกลาง ปลายทางขณะติดตั้งโมดูล การใช้งานเริ่มต้นของ ส่วนความคืบหน้าจะแสดง UI พื้นฐานพร้อมแถบความคืบหน้าและจัดการ ข้อผิดพลาดในการติดตั้ง
![หน้าจอโหลด 2 หน้าจอที่แสดง UI พร้อมแถบความคืบหน้าขณะนำทาง
เป็นโมดูลฟีเจอร์เป็นครั้งแรก](https://developer.android.com/static/images/guide/navigation/dfm-nav-loading.png?hl=th)
หากต้องการปรับแต่ง UI นี้ หรือจัดการการติดตั้งด้วยตนเอง ความคืบหน้าจากภายในหน้าจอแอปของคุณ โปรดดู ปรับแต่งส่วนย่อยความคืบหน้า และ ติดตามสถานะของคำขอในหัวข้อนี้
ปลายทางที่ไม่ได้ระบุ app:moduleName
จะยังคงทำงานต่อไปหากไม่มี
เปลี่ยนแปลงและทํางานเสมือนว่าแอปของคุณใช้ NavHostFragment
ปกติ
ปรับแต่งส่วนย่อยความคืบหน้า
คุณลบล้างการใช้งานส่วนความคืบหน้าสําหรับกราฟการนำทางแต่ละรายการได้
โดยการตั้งค่าแอตทริบิวต์ app:progressDestination
เป็นรหัสของปลายทาง
ที่ต้องการใช้เพื่อจัดการความคืบหน้าของการติดตั้ง ความคืบหน้าที่กำหนดเอง
ปลายทางควรเป็น
Fragment
ที่มาจาก
AbstractProgressFragment
คุณต้องลบล้างเมธอด Abstract สำหรับการแจ้งเตือนเกี่ยวกับการติดตั้ง
ความคืบหน้า ข้อผิดพลาด และเหตุการณ์อื่นๆ จากนั้นคุณจะแสดงความคืบหน้าในการติดตั้งได้ใน
UI ที่ต้องการ
การติดตั้งใช้งานเริ่มต้น
DefaultProgressFragment
ใช้ API นี้เพื่อแสดงความคืบหน้าในการติดตั้ง
ตรวจสอบสถานะของคำขอ
ไลบรารี Dynamic Navigator ช่วยให้คุณสามารถใช้ขั้นตอน UX ที่คล้ายกับ 1 ใน แนวทางปฏิบัติแนะนำเกี่ยวกับ UX สำหรับการนำส่งแบบออนดีมานด์ ซึ่งผู้ใช้อยู่ในบริบทของหน้าจอก่อนหน้าขณะที่รอ ให้เสร็จสิ้น คุณจึงไม่จำเป็นต้องแสดงตัวกลาง UI หรือส่วนย่อยของความคืบหน้าเลย
![ซึ่งแสดงแถบนำทางด้านล่างพร้อมด้วยไอคอนที่แสดงถึง
โมดูลฟีเจอร์กำลังดาวน์โหลด](https://developer.android.com/static/images/guide/navigation/nav-dfm-ui.png?hl=th)
ในกรณีนี้ คุณจะต้องรับผิดชอบ การตรวจสอบและจัดการสถานะการติดตั้งทั้งหมด การเปลี่ยนแปลงความคืบหน้า ข้อผิดพลาด เป็นต้น
ในการเริ่มต้นขั้นตอนการนำทางแบบไม่บล็อกนี้ ให้ส่ง
DynamicExtras
ที่มีแอตทริบิวต์
DynamicInstallMonitor
ถึง
NavController.navigate()
,
ดังที่ปรากฏในตัวอย่างต่อไปนี้
Kotlin
val navController = ... val installMonitor = DynamicInstallMonitor() navController.navigate( destinationId, null, null, DynamicExtras(installMonitor) )
Java
NavController navController = ... DynamicInstallMonitor installMonitor = new DynamicInstallMonitor(); navController.navigate( destinationId, null, null, new DynamicExtras(installMonitor); )
ทันทีหลังจากที่โทรหา navigate()
คุณควรตรวจสอบค่าของ
installMonitor.isInstallRequired
เพื่อดูว่าระบบพยายามไปยังส่วนต่างๆ หรือไม่
ในการติดตั้งโมดูลฟีเจอร์
- หากค่าเป็น
false
แสดงว่าคุณไปยังปลายทางปกติและไม่ ต้องดำเนินการอื่นๆ อีกไหม หากค่าเป็น
true
คุณควรเริ่มสังเกตออบเจ็กต์LiveData
ที่ ขณะนี้อยู่ในinstallMonitor.status
ออบเจ็กต์LiveData
นี้ปล่อยSplitInstallSessionState
จากไลบรารี Play Core การอัปเดตเหล่านี้มีการติดตั้ง เหตุการณ์ความคืบหน้าที่คุณสามารถใช้เพื่ออัปเดต UI อย่าลืมจัดการทั้งหมด สถานะที่เกี่ยวข้องตามที่ระบุไว้ใน คู่มือ Play Core มี การขอการยืนยันผู้ใช้ หากจำเป็นKotlin
val navController = ... val installMonitor = DynamicInstallMonitor() navController.navigate( destinationId, null, null, DynamicExtras(installMonitor) ) if (installMonitor.isInstallRequired) { installMonitor.status.observe(this, object : Observer<SplitInstallSessionState> { override fun onChanged(sessionState: SplitInstallSessionState) { when (sessionState.status()) { SplitInstallSessionStatus.INSTALLED -> { // Call navigate again here or after user taps again in the UI: // navController.navigate(destinationId, destinationArgs, null, null) } SplitInstallSessionStatus.REQUIRES_USER_CONFIRMATION -> { SplitInstallManager.startConfirmationDialogForResult(...) } // Handle all remaining states: SplitInstallSessionStatus.FAILED -> {} SplitInstallSessionStatus.CANCELED -> {} } if (sessionState.hasTerminalStatus()) { installMonitor.status.removeObserver(this); } } }); }
Java
NavController navController = ... DynamicInstallMonitor installMonitor = new DynamicInstallMonitor(); navController.navigate( destinationId, null, null, new DynamicExtras(installMonitor); ) if (installMonitor.isInstallRequired()) { installMonitor.getStatus().observe(this, new Observer<SplitInstallSessionState>() { @Override public void onChanged(SplitInstallSessionState sessionState) { switch (sessionState.status()) { case SplitInstallSessionStatus.INSTALLED: // Call navigate again here or after user taps again in the UI: // navController.navigate(mDestinationId, mDestinationArgs, null, null); break; case SplitInstallSessionStatus.REQUIRES_USER_CONFIRMATION: SplitInstallManager.startConfirmationDialogForResult(...) break; // Handle all remaining states: case SplitInstallSessionStatus.FAILED: break; case SplitInstallSessionStatus.CANCELED: break; } if (sessionState.hasTerminalStatus()) { installMonitor.getStatus().removeObserver(this); } } }); }
เมื่อติดตั้งเสร็จแล้ว ออบเจ็กต์ LiveData
จะปล่อย
สถานะ SplitInstallSessionStatus.INSTALLED
จากนั้นคุณควรโทร
NavController.navigate()
อีกครั้ง เนื่องจากตอนนี้ติดตั้งโมดูลแล้ว การเรียก
และแอปก็จะนำทางไปยังปลายทางตามที่คาดไว้
หลังจากถึงสถานะเทอร์มินัล เช่น เมื่อการติดตั้งเสร็จสมบูรณ์หรือเมื่อเสร็จสมบูรณ์
ติดตั้งไม่สำเร็จ คุณควรนำผู้สังเกตการณ์ LiveData
ออกเพื่อหลีกเลี่ยงการใช้หน่วยความจำ
การรั่วไหล คุณสามารถตรวจสอบว่าสถานะดังกล่าวแสดงถึงสถานะของเทอร์มินัลหรือไม่โดยใช้
SplitInstallSessionStatus.hasTerminalStatus()
โปรดดู AbstractProgressFragment
สำหรับตัวอย่างการใช้งานของผู้สังเกตการณ์รายนี้
กราฟที่มี
ไลบรารี Dynamic Navigator สนับสนุนการรวมกราฟที่กำหนดไว้ใน โมดูลฟีเจอร์ เพื่อรวมกราฟที่กำหนดไว้ในฟีเจอร์ ให้ทำดังนี้
ใช้
<include-dynamic/>
แทน<include/>
ตามที่แสดงในตัวอย่างต่อไปนี้ ตัวอย่าง:<include-dynamic android:id="@+id/includedGraph" app:moduleName="includedgraphfeature" app:graphResName="included_feature_nav" app:graphPackage="com.google.android.samples.dynamic_navigator.included_graph_feature" />
ภายใน
<include-dynamic ... />
คุณต้องระบุแอตทริบิวต์ต่อไปนี้app:graphResName
: ชื่อไฟล์ทรัพยากรของกราฟการนำทาง ได้มาจากชื่อไฟล์ของกราฟ ตัวอย่างเช่น หากกราฟอยู่ในres/navigation/nav_graph.xml
ชื่อทรัพยากรคือnav_graph
android:id
- รหัสปลายทางของกราฟ ไลบรารี Dynamic Navigator ไม่สนใจค่าandroid:id
ที่พบในองค์ประกอบรูทของ กราฟที่รวมไว้app:moduleName
: ชื่อแพ็กเกจของโมดูล
ใช้ GrapPackage ที่ถูกต้อง
คุณต้องทำให้ app:graphPackage
ถูกต้องในฐานะการนำทาง
คอมโพเนนต์จะไม่สามารถรวม navGraph
ที่ระบุจากฟีเจอร์
ไม่เช่นนั้น
ชื่อแพ็กเกจของโมดูลฟีเจอร์แบบไดนามิกสร้างขึ้นโดยการเพิ่ม
ชื่อของโมดูลเป็น applicationId
ของโมดูลแอปฐาน ดังนั้น หาก
โมดูลแอปฐานมี applicationId
เป็น com.example.dynamicfeatureapp
และ
โมดูลฟีเจอร์แบบไดนามิกมีชื่อว่า DynamicFeatureModule
จากนั้นแพ็กเกจ
ของโมดูลแบบไดนามิกจะ
com.example.dynamicfeatureapp.DynamicFeatureModule
ชื่อแพ็กเกจนี้คือ
คำนึงถึงตัวพิมพ์เล็กและตัวพิมพ์ใหญ่
หากคุณไม่แน่ใจ คุณสามารถยืนยันชื่อแพ็กเกจของโมดูลฟีเจอร์
โดยการตรวจสอบ AndroidManifest.xml
ที่สร้างขึ้น หลังจากสร้างโครงการแล้ว
ถึง <DynamicFeatureModule>/build/intermediates/merged_manifest/debug/AndroidManifest.xml
ซึ่งควรมีลักษณะดังนี้
<manifest xmlns:android="http://schemas.android.com/apk/res/android" xmlns:dist="http://schemas.android.com/apk/distribution" featureSplit="DynamicFeatureModule" package="com.example.dynamicfeatureapp" android:versionCode="1" android:versionName="1.0" > <uses-sdk android:minSdkVersion="21" android:targetSdkVersion="30" /> <dist:module dist:instant="false" dist:title="@string/title_dynamicfeaturemodule" > <dist:delivery> <dist:install-time /> </dist:delivery> <dist:fusing dist:include="true" /> </dist:module> <application /> </manifest>
ค่า featureSplit
ควรตรงกับชื่อของโมดูลฟีเจอร์แบบไดนามิก และแพ็กเกจจะตรงกับ applicationId
ของโมดูลแอปฐาน app:graphPackage
คือชุดค่าผสมของ com.example.dynamicfeatureapp.DynamicFeatureModule
การไปยังกราฟการนำทางรวมแบบไดนามิก
สามารถไปที่ startDestination
ของ
กราฟการนำทาง include-dynamic
โดยโมดูลแบบไดนามิกจะทำหน้าที่
กราฟการนำทางของตนเอง และแอปหลักก็ไม่มีความรู้ด้านนี้เช่นกัน
กลไกการรวมแบบไดนามิกช่วยให้โมดูลแอปพื้นฐานรวม
กราฟการนำทางที่ซ้อนกัน
ที่กำหนดภายในโมดูลแบบไดนามิก กราฟการนำทางที่ฝังนี้จะทำงาน
เหมือนกราฟการนำทางที่ฝังไว้ กราฟการนำทางระดับรูท (ซึ่งก็คือระดับบนสุด
ของกราฟเชิงซ้อน) สามารถกำหนดได้เฉพาะกราฟการนำทางที่ซ้อนกันเป็น
ปลายทาง ไม่ใช่รายการย่อย ดังนั้นระบบจึงใช้ startDestination
เมื่อ
กราฟรวมการนำทางแบบไดนามิกคือปลายทาง
ข้อจำกัด
- กราฟที่รวมแบบไดนามิกยังไม่รองรับลิงก์ในรายละเอียดในขณะนี้
- กราฟแบบซ้อนที่โหลดแบบไดนามิก (กล่าวคือ องค์ประกอบ
<navigation>
ที่มีapp:moduleName
) ยังไม่รองรับ Deep Link ในขณะนี้