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
หากต้องการย้ายไปยังการเขียนในการนำทาง ให้ทำตามขั้นตอนต่อไปนี้
- เพิ่มทรัพยากร 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
ในตำแหน่งที่ Composable ทั้งหมดที่ต้องใช้การอ้างอิงจะมีสิทธิ์เข้าถึง (โดยปกติจะอยู่ใน Composable ของ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
เรียกข้อมูลที่ซับซ้อนขณะนำทาง
เราขอแนะนำอย่างยิ่งว่าอย่าส่งออบเจ็กต์ข้อมูลที่ซับซ้อนไปมาเมื่อไปยังส่วนต่างๆ แต่ให้ส่งข้อมูลขั้นต่ำที่จำเป็น เช่น ตัวระบุที่ไม่ซ้ำกันหรือรหัสรูปแบบอื่นๆ เป็นอาร์กิวเมนต์เมื่อดำเนินการไปยังส่วนต่างๆ แทน คุณควรจัดเก็บออบเจ็กต์ที่ซับซ้อนเป็นข้อมูลในแหล่งข้อมูลที่ถูกต้องแห่งเดียว เช่น เลเยอร์ข้อมูล โปรดดูข้อมูลเพิ่มเติมที่หัวข้อการดึงข้อมูลที่ซับซ้อนเมื่อไปยังส่วนต่างๆ
หาก Fragments ส่งผ่านออบเจ็กต์ที่ซับซ้อนเป็นอาร์กิวเมนต์ ให้พิจารณาเปลี่ยนโครงสร้างภายในโค้ดของคุณก่อน โดยให้สามารถจัดเก็บและดึงข้อมูลออบเจ็กต์เหล่านี้จากชั้นข้อมูลได้ ดูตัวอย่างในที่เก็บ "Now in Android"
ข้อจำกัด
ส่วนนี้จะอธิบายข้อจํากัดปัจจุบันของ 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 ปิดอยู่
- การไปยังส่วนต่างๆ ด้วยเครื่องมือเขียน
- เขียนและไลบรารีอื่นๆ
- ข้อควรพิจารณาอื่นๆ