Navigation Compose API ช่วยให้คุณไปยังส่วนต่างๆ ของคอมโพสิเบิลในแอป Compose ได้ พร้อมทั้งใช้ประโยชน์จากคอมโพเนนต์ โครงสร้างพื้นฐาน และฟีเจอร์ของ Jetpack Navigation
หน้านี้จะอธิบายวิธีย้ายข้อมูลจาก Jetpack Navigation ที่ใช้ Fregment ไปยัง Navigation Compose ซึ่งเป็นส่วนหนึ่งของการย้ายข้อมูล UI ขนาดใหญ่ที่ใช้ View ไปยัง Jetpack Compose
ข้อกําหนดเบื้องต้นในการย้ายข้อมูล
คุณสามารถย้ายข้อมูลไปยัง Navigation Compose ได้เมื่อแทนที่คอมโพเนนต์ย่อยทั้งหมดด้วยคอมโพสิชันหน้าจอที่เกี่ยวข้อง คอมโพสิชันหน้าจออาจมีเนื้อหาแบบผสมผสานระหว่างคอมโพสิชันและมุมมอง แต่ปลายทางการนำทางทั้งหมดต้องเป็นคอมโพสิชันเพื่อให้การย้ายข้อมูลคอมโพสิชันการนำทางทำงานได้ ในระหว่างนี้ คุณควรใช้คอมโพเนนต์การนําทางที่อิงตาม FRGMENT ในโค้ดเบสของ View และ Compose ที่ทำงานร่วมกันต่อไป ดูข้อมูลเพิ่มเติมได้ที่เอกสารประกอบเกี่ยวกับการทํางานร่วมกันในการนําทาง
การใช้ Navigation Compose ในแอป Compose เท่านั้นไม่ใช่ข้อกําหนดเบื้องต้น คุณใช้ คอมโพเนนต์การนำทางที่อิงตามข้อมูลโค้ดต่อไปได้ ตราบใดที่คุณยังใช้ข้อมูลโค้ดเพื่อโฮสต์เนื้อหาที่คอมโพสิเบิล
ขั้นตอนการย้ายข้อมูล
ไม่ว่าคุณจะทําตามกลยุทธ์การย้ายข้อมูลที่แนะนําหรือใช้แนวทางอื่น คุณก็จะไปถึงจุดที่ปลายทางการนำทางทั้งหมดเป็นคอมโพสิเบิลหน้าจอ โดยมี Fragment ทำหน้าที่เป็นคอนเทนเนอร์คอมโพสิเบิลเท่านั้น ในขั้นตอนนี้ คุณสามารถย้ายข้อมูลไปยังการเขียนแบบนําทาง
หากแอปของคุณเป็นไปตามรูปแบบการออกแบบ UDF และคำแนะนำเกี่ยวกับสถาปัตยกรรมอยู่แล้ว การย้ายข้อมูลไปยัง Jetpack Compose และ Navigation Compose จะไม่จําเป็นต้องรีแฟกทอริงเลเยอร์อื่นๆ ของแอปมากนัก ยกเว้นเลเยอร์ UI
หากต้องการย้ายข้อมูลไปยัง Navigation Compose ให้ทําตามขั้นตอนต่อไปนี้
- เพิ่มทรัพยากร Dependency ของ Navigation Compose ลงในแอป
สร้างคอมโพสิชัน
App-level
แล้วเพิ่มลงในActivity
ของคุณเป็นจุดแรกเข้าของคอมโพสิชัน แทนการตั้งค่าเลย์เอาต์มุมมอง ดังนี้class SampleActivity : ComponentActivity() { override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) // setContentView<ActivitySampleBinding>(this, R.layout.activity_sample) setContent { SampleApp(/* ... */) } } }
สร้างประเภทสําหรับปลายทางการนําทางแต่ละแห่ง ใช้
data object
สำหรับปลายทางที่ไม่ต้องใช้ข้อมูล และdata class
หรือclass
สำหรับปลายทางที่ต้องใช้ข้อมูล@Serializable data object First @Serializable data class Second(val id: String) @Serializable data object Third
ตั้งค่า
NavController
ไว้ในตำแหน่งที่คอมโพสิเบิลทั้งหมดที่ต้องอ้างอิงเข้าถึงได้ (โดยปกติจะอยู่ภายในคอมโพสิเบิลApp
) แนวทางนี้เป็นไปตามหลักการของการยกระดับสถานะ และให้คุณใช้NavController
เป็นแหล่งข้อมูลสำหรับการไปยังส่วนต่างๆ ของหน้าจอแบบคอมโพสิเบิลและดูแลรักษากองซ้อนที่ซ้อนกันอยู่@Composable fun SampleApp() { val navController = rememberNavController() // ... }
สร้าง
NavHost
ของแอปภายในคอมโพสิชันApp
และส่งnavController
ดังนี้@Composable fun SampleApp() { val navController = rememberNavController() SampleNavHost(navController = navController) } @Composable fun SampleNavHost( navController: NavHostController ) { NavHost(navController = navController, startDestination = First) { // ... } }
เพิ่มปลายทาง
composable
เพื่อสร้างกราฟการนำทาง หากก่อนหน้านี้มีการย้ายข้อมูลหน้าจอแต่ละหน้าจอไปยัง Compose ขั้นตอนนี้จะมีเพียงการดึงข้อมูลคอมโพสิชันหน้าจอเหล่านี้จาก Fregment ไปยังปลายทางcomposable
ต่อไปนี้class FirstFragment : Fragment() { override fun onCreateView( inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle? ): View { return ComposeView(requireContext()).apply { setContent { // FirstScreen(...) EXTRACT FROM HERE } } } } @Composable fun SampleNavHost( navController: NavHostController ) { NavHost(navController = navController, startDestination = First) { composable<First> { FirstScreen(/* ... */) // EXTRACT TO HERE } composable<Second> { SecondScreen(/* ... */) } // ... } }
หากคุณทําตามคําแนะนําเกี่ยวกับการจัดโครงสร้าง UI ของ Compose โดยเฉพาะวิธีส่ง
ViewModel
และเหตุการณ์การนําทางไปยัง Composable ขั้นตอนถัดไปคือเปลี่ยนวิธีระบุViewModel
ให้กับ Composable แต่ละหน้าจอ คุณมักจะใช้การฉีด Hilt และจุดผสานรวมกับ Compose และ Navigation ผ่านhiltViewModel
ดังนี้@Composable fun FirstScreen( // viewModel: FirstViewModel = viewModel(), viewModel: FirstViewModel = hiltViewModel(), onButtonClick: () -> Unit = {}, ) { // ... }
แทนที่การเรียกใช้การนําทาง
findNavController()
ทั้งหมดด้วยnavController
และส่งการเรียกใช้เหล่านี้เป็นเหตุการณ์การนําทางไปยังหน้าจอคอมโพสิเบิลแต่ละหน้าจอแทนการส่งnavController
ทั้งหมด แนวทางนี้เป็นไปตามแนวทางปฏิบัติแนะนำในการแสดงเหตุการณ์จากฟังก์ชันคอมโพสิเบิลต่อผู้เรียกใช้ และทำให้navController
เป็นแหล่งข้อมูลที่ถูกต้องเพียงแหล่งเดียวคุณสามารถส่งข้อมูลไปยังปลายทางได้โดยการสร้างอินสแตนซ์ของคลาสเส้นทางที่กําหนดไว้สําหรับปลายทางนั้น จากนั้นคุณก็รับ
ViewModel
ได้จากรายการสแต็กด้านหลังที่ปลายทางโดยตรง หรือจากViewModel
โดยใช้SavedStateHandle.toRoute()
@Composable fun SampleNavHost( navController: NavHostController ) { NavHost(navController = navController, startDestination = First) { composable<First> { FirstScreen( onButtonClick = { // findNavController().navigate(firstScreenToSecondScreenAction) navController.navigate(Second(id = "ABC")) } ) } composable<Second> { backStackEntry -> val secondRoute = backStackEntry.toRoute<Second>() SecondScreen( id = secondRoute.id, onIconClick = { // findNavController().navigate(secondScreenToThirdScreenAction) navController.navigate(Third) } ) } // ... } }
ลบ Fregment, เลย์เอาต์ XML ที่เกี่ยวข้อง, การนำทางและทรัพยากรอื่นๆ ที่ไม่จำเป็น รวมถึงการพึ่งพา Fregment และการนำทางของ Jetpack ที่ล้าสมัย
คุณดูขั้นตอนเดียวกันพร้อมรายละเอียดเพิ่มเติมเกี่ยวกับ Navigation Compose ได้ในเอกสารประกอบการตั้งค่า
กรณีการใช้งานทั่วไป
ไม่ว่าคุณจะใช้คอมโพเนนต์การไปยังส่วนต่างๆ รายการใด หลักการในการไปยังส่วนต่างๆ เดียวกันก็จะมีผลบังคับใช้
กรณีการใช้งานทั่วไปเมื่อย้ายข้อมูลมีดังนี้
- ไปยังคอมโพสิเบิล
- ไปยังส่วนต่างๆ ด้วยอาร์กิวเมนต์
- Deep Link
- การนําทางที่ฝัง
- การผสานรวมกับแถบนําทางด้านล่าง
- การผสานรวมกับคอมโพเนนต์การนําทางที่กําหนดเอง
ดูข้อมูลโดยละเอียดเพิ่มเติมเกี่ยวกับกรณีการใช้งานเหล่านี้ได้ที่การไปยังส่วนต่างๆ ด้วย Compose
ดึงข้อมูลที่ซับซ้อนเมื่อนำทาง
เราขอแนะนำอย่างยิ่งว่าอย่าส่งออบเจ็กต์ข้อมูลที่ซับซ้อนไปมาเมื่อไปยังส่วนต่างๆ แต่ให้ส่งข้อมูลที่จำเป็นขั้นต่ำ เช่น ตัวระบุที่ไม่ซ้ำกันหรือรหัสรูปแบบอื่นๆ เป็นอาร์กิวเมนต์เมื่อดำเนินการไปยังส่วนต่างๆ คุณควรจัดเก็บออบเจ็กต์ที่ซับซ้อนเป็นข้อมูลในแหล่งข้อมูลที่ถูกต้องแห่งเดียว เช่น เลเยอร์ข้อมูล โปรดดูข้อมูลเพิ่มเติมที่หัวข้อการดึงข้อมูลที่ซับซ้อนเมื่อไปยังส่วนต่างๆ
หากมีการส่งออบเจ็กต์ที่ซับซ้อนเป็นอาร์กิวเมนต์ ให้ลองปรับโครงสร้างโค้ดก่อน โดยให้สามารถจัดเก็บและดึงข้อมูลออบเจ็กต์เหล่านี้จากเลเยอร์ข้อมูล ดูตัวอย่างได้ที่ที่เก็บ Now in Android
ข้อจำกัด
ส่วนนี้จะอธิบายข้อจํากัดปัจจุบันของ Navigation Compose
การย้ายข้อมูลไปยัง Navigation Compose เพิ่มขึ้น
ปัจจุบันคุณใช้ Navigation Compose ไม่ได้ขณะที่ยังใช้ Fragments เป็นปลายทางในโค้ด หากต้องการเริ่มใช้ Navigation Compose จุดหมายทั้งหมดต้องเป็นแบบคอมโพสิเบิล คุณติดตามคำขอฟีเจอร์นี้ในเครื่องมือติดตามปัญหาได้
ภาพเคลื่อนไหวของการเปลี่ยน
ตั้งแต่ Navigation 2.7.0-alpha01 เป็นต้นไป NavHost
จะรองรับการตั้งค่าทรานซิชันที่กำหนดเองโดยตรง ซึ่งก่อนหน้านี้รองรับใน AnimatedNavHost
อ่านบันทึกประจำรุ่นเพื่อดูข้อมูลเพิ่มเติม
ดูข้อมูลเพิ่มเติม
ดูข้อมูลเพิ่มเติมเกี่ยวกับการย้ายข้อมูลไปยัง Navigation Compose ได้ที่แหล่งข้อมูลต่อไปนี้
- Navigation Compose Codelab: ดูข้อมูลเบื้องต้นเกี่ยวกับ Navigation Compose ด้วย Codelab แบบปฏิบัติจริง
- ตอนนี้อยู่ในที่เก็บข้อมูล Android: แอป Android ที่ใช้งานได้อย่างเต็มรูปแบบซึ่งสร้างขึ้นด้วย Kotlin และ Jetpack Compose ทั้งหมด โดยเป็นไปตามแนวทางปฏิบัติแนะนำด้านการออกแบบและพัฒนาของ Android และมี Navigation Compose
- การย้ายข้อมูล Sunflower ไปยัง Jetpack Compose: บล็อกโพสต์ที่บันทึกเส้นทางการย้ายข้อมูลของแอปตัวอย่าง Sunflower จาก Views ไปยัง Compose ซึ่งรวมถึงการย้ายข้อมูลไปยัง Navigation Compose ด้วย
- Jetnews สำหรับทุกหน้าจอ: บล็อกโพสต์ที่บันทึกการแยกส่วนและย้ายข้อมูลตัวอย่าง Jetnews เพื่อรองรับหน้าจอทั้งหมดด้วย Jetpack Compose และ Navigation Compose
แนะนำสำหรับคุณ
- หมายเหตุ: ข้อความลิงก์จะแสดงเมื่อ JavaScript ปิดอยู่
- การไปยังส่วนต่างๆ ด้วยเครื่องมือเขียน
- คอมโพสิทและไลบรารีอื่นๆ
- ข้อควรพิจารณาอื่นๆ