Navigation Compose API ช่วยให้คุณไปยังส่วนต่างๆ ระหว่าง Composable ใน แอป Compose ได้ พร้อมทั้งใช้ประโยชน์จากคอมโพเนนต์ โครงสร้างพื้นฐาน และฟีเจอร์ของ Jetpack Navigation
หน้านี้อธิบายวิธีย้ายข้อมูลจาก Jetpack Navigation ที่อิงตาม Fragment ไปยัง Navigation Compose ซึ่งเป็นส่วนหนึ่งของการย้ายข้อมูล UI ที่อิงตาม View ไปยัง Jetpack Compose ที่มีขนาดใหญ่กว่า
ข้อกำหนดเบื้องต้นในการย้ายข้อมูล
คุณจะย้ายข้อมูลไปยัง Navigation Compose ได้เมื่อแทนที่ Fragment ทั้งหมดด้วย Composable ของหน้าจอที่เกี่ยวข้องได้ Composable ของหน้าจออาจมีเนื้อหา Compose และ View ผสมกัน แต่ปลายทางการนำทางทั้งหมดต้องเป็น Composable เพื่อเปิดใช้การย้ายข้อมูล Navigation Compose ในระหว่างนี้ คุณควรใช้คอมโพเนนต์การนำทางที่อิงตาม Fragment ต่อไปใน View และ ฐานโค้ด Compose ที่ทำงานร่วมกัน ดูข้อมูลเพิ่มเติมได้ที่เอกสารประกอบเกี่ยวกับการทำงานร่วมกันของการนำทาง
การใช้ Navigation Compose ในแอป Compose เท่านั้นไม่ใช่ข้อกำหนดเบื้องต้น คุณสามารถใช้ คอมโพเนนต์การนำทางที่อิงตาม Fragment ต่อไปได้ตราบใดที่คุณยังใช้ Fragment สำหรับโฮสต์เนื้อหาที่ประกอบได้
ขั้นตอนการย้ายข้อมูล
ไม่ว่าคุณจะใช้กลยุทธ์การย้ายข้อมูลที่แนะนําหรือใช้วิธีอื่น คุณจะมาถึงจุดที่ปลายทางการนําทางทั้งหมดเป็น Composable ของหน้าจอ โดย Fragment จะทําหน้าที่เป็นเพียงคอนเทนเนอร์ Composable ในขั้นตอนนี้ คุณสามารถย้ายข้อมูลไปยัง Navigation Compose ได้
หากแอปของคุณเป็นไปตามรูปแบบการออกแบบ UDF และคำแนะนำเกี่ยวกับ สถาปัตยกรรมของเราอยู่แล้ว การย้ายข้อมูลไปยัง Jetpack Compose และ Navigation Compose ก็ไม่น่า ต้องมีการปรับโครงสร้างเลเยอร์อื่นๆ ของแอปครั้งใหญ่ นอกเหนือจากเลเยอร์ UI
หากต้องการย้ายข้อมูลไปยัง Navigation Compose ให้ทำตามขั้นตอนต่อไปนี้
- เพิ่มทรัพยากร Dependency ของ Navigation Compose ลงในแอป
สร้าง
App-level
ที่ใช้ร่วมกันได้ แล้วเพิ่มลงในActivity
เป็น จุดแรกเข้าของ Compose แทนที่การตั้งค่าเลย์เอาต์ View ดังนี้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 ทั้งหมดที่ต้องอ้างอิงถึงเข้าถึงได้ (โดยปกติจะอยู่ภายใน ComposableApp
) แนวทางนี้เป็นไปตามหลักการของการยกระดับสถานะ และช่วยให้คุณใช้NavController
เป็นแหล่งข้อมูลที่เชื่อถือได้สำหรับการ ไปยังมาระหว่างหน้าจอที่ประกอบได้และรักษา Back Stack@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 แล้ว ขั้นตอนนี้จะมีเพียงการ ดึงข้อมูล Composable ของหน้าจอเหล่านี้จาก Fragment ไปยัง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
และเหตุการณ์การนำทางไปยัง Composables ขั้นตอนถัดไปคือการเปลี่ยนวิธีระบุViewModel
ให้กับ Composables ของแต่ละหน้าจอ คุณมักจะใช้การแทรก Hilt และจุดรวมของ Hilt กับ Compose และ Navigation ผ่านhiltViewModel
ได้@Composable fun FirstScreen( // viewModel: FirstViewModel = viewModel(), viewModel: FirstViewModel = hiltViewModel(), onButtonClick: () -> Unit = {}, ) { // ... }
แทนที่การเรียกใช้การนำทาง
findNavController()
ทั้งหมดด้วยการเรียกใช้navController
และส่งการเรียกใช้เหล่านี้เป็นเหตุการณ์การนำทางไปยังแต่ละหน้าจอที่ใช้ได้ แทนที่จะส่งnavController
ทั้งหมด แนวทางนี้เป็นไปตามแนวทางปฏิบัติแนะนำในการแสดงเหตุการณ์จากฟังก์ชันที่ประกอบได้ต่อผู้เรียกใช้ และ ทำให้navController
เป็นแหล่งข้อมูลที่ถูกต้องเพียงแห่งเดียวคุณส่งข้อมูลไปยังปลายทางได้โดยการสร้างอินสแตนซ์ของคลาสเส้นทาง ที่กำหนดไว้สำหรับปลายทางนั้น จากนั้นจะรับได้โดยตรง จากรายการในสแต็กย้อนกลับที่ปลายทาง หรือจาก
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) } ) } // ... } }
นำ Fragment, เลย์เอาต์ XML ที่เกี่ยวข้อง, การนำทางที่ไม่จำเป็น และทรัพยากรอื่นๆ รวมถึง Fragment ที่ล้าสมัยและการอ้างอิง Jetpack Navigation ออกทั้งหมด
คุณดูขั้นตอนเดียวกันนี้พร้อมรายละเอียดเพิ่มเติมที่เกี่ยวข้องกับ Navigation Compose ได้ในเอกสารประกอบการตั้งค่า
กรณีการใช้งานทั่วไป
ไม่ว่าคุณจะใช้คอมโพเนนต์การนำทางใด หลักการเดียวกันของการนำทางจะใช้ได้
กรณีการใช้งานทั่วไปเมื่อย้ายข้อมูลมีดังนี้
- ไปยัง Composable
- ไปยังส่วนต่างๆ ด้วยอาร์กิวเมนต์
- Deep Link
- การนำทางแบบซ้อน
- การผสานรวมกับแถบนำทางด้านล่าง
- การผสานรวมกับคอมโพเนนต์การนำทางที่กำหนดเอง
ดูข้อมูลโดยละเอียดเพิ่มเติมเกี่ยวกับกรณีการใช้งานเหล่านี้ได้ที่การไปยังส่วนต่างๆ ด้วย Compose
ดึงข้อมูลที่ซับซ้อนเมื่อนำทาง
เราขอแนะนำอย่างยิ่งว่าอย่าส่งต่อออบเจ็กต์ข้อมูลที่ซับซ้อนเมื่อไปยังส่วนต่างๆ ให้ส่งข้อมูลที่จำเป็นขั้นต่ำ เช่น ตัวระบุที่ไม่ซ้ำกันหรือ รูปแบบอื่นๆ ของรหัส เป็นอาร์กิวเมนต์เมื่อดำเนินการนำทางแทน คุณควรจัดเก็บออบเจ็กต์ที่ซับซ้อนเป็นข้อมูลในแหล่งข้อมูลที่ถูกต้องแห่งเดียว เช่น dataLayer ดูข้อมูลเพิ่มเติมได้ที่หัวข้อการดึงข้อมูลที่ซับซ้อนเมื่อ ไปยังส่วนต่างๆ
หาก Fragment ส่งออบเจ็กต์ที่ซับซ้อนเป็นอาร์กิวเมนต์ ให้ลองรีแฟกเตอร์ โค้ดก่อนในลักษณะที่อนุญาตให้จัดเก็บและดึงข้อมูลออบเจ็กต์เหล่านี้จาก เลเยอร์ข้อมูล ดูตัวอย่างได้ในที่เก็บ Now in Android
ข้อจำกัด
ส่วนนี้จะอธิบายข้อจำกัดปัจจุบันของ Navigation Compose
การย้ายข้อมูลไปยัง Navigation Compose แบบค่อยเป็นค่อยไป
ขณะนี้คุณยังใช้ Navigation Compose ไม่ได้ในขณะที่ยังใช้ Fragment เป็น ปลายทางในโค้ด หากต้องการเริ่มใช้ Navigation Compose ปลายทางทั้งหมดของคุณต้องเป็น Composable คุณติดตามคำขอฟีเจอร์นี้ได้ใน เครื่องมือติดตามปัญหา
ภาพเคลื่อนไหวการเปลี่ยน
ตั้งแต่ Navigation 2.7.0-alpha01 เป็นต้นไป การรองรับการตั้งค่าภาพเคลื่อนไหวที่กำหนดเอง ซึ่งก่อนหน้านี้มาจาก AnimatedNavHost
จะได้รับการรองรับโดยตรงใน NavHost
แล้ว อ่านบันทึกประจำรุ่นเพื่อดูข้อมูลเพิ่มเติม
ดูข้อมูลเพิ่มเติม
ดูข้อมูลเพิ่มเติมเกี่ยวกับการย้ายข้อมูลไปยัง Navigation Compose ได้ที่แหล่งข้อมูลต่อไปนี้
- Codelab การนำทางด้วย Compose: เรียนรู้พื้นฐานของการนำทางด้วย Compose ด้วย Codelab เชิงปฏิบัติ
- ที่เก็บ Now in Android: แอป Android ที่ทำงานได้อย่างเต็มรูปแบบ สร้างขึ้นด้วย Kotlin และ Jetpack Compose ทั้งหมด ซึ่งเป็นไปตามการออกแบบ Android และแนวทางปฏิบัติแนะนำในการพัฒนา รวมถึงมี Navigation Compose
- การย้ายข้อมูล Sunflower ไปยัง Jetpack Compose: บล็อกโพสต์ที่ บันทึกเส้นทางการย้ายข้อมูลของแอปตัวอย่าง Sunflower จาก Views ไปยัง Compose ซึ่งรวมถึงการย้ายข้อมูลไปยัง Navigation Compose ด้วย
- Jetnews สำหรับทุกหน้าจอ: บล็อกโพสต์ที่บันทึกการ รีแฟกเตอร์และการย้ายข้อมูลตัวอย่าง Jetnews เพื่อรองรับทุกหน้าจอด้วย Jetpack Compose และ Navigation Compose
แนะนำสำหรับคุณ
- หมายเหตุ: ข้อความลิงก์จะแสดงเมื่อ JavaScript ปิดอยู่
- การไปยังส่วนต่างๆ ด้วย Compose
- Compose และไลบรารีอื่นๆ
- ข้อควรพิจารณาอื่นๆ