NavHost — คืออะไร การสร้างกราฟนำทางและเส้นทางใน Jetpack Compose

ผู้แต่ง: IT Sectr เผยแพร่เมื่อ: 2026-06-30 เวลาอ่าน: 7 นาที

NavHost คือคอนเทนเนอร์ composable ที่ทำหน้าที่เป็นจุดเริ่มต้นสำหรับกราฟนำทางใน Jetpack Compose โดยเชื่อมโยง NavController กับชุดของเส้นทางและเรนเดอร์หน้าจอปัจจุบันตามสถานะของแบ็กสแต็ก ตามข้อมูลของ Android Developers (2025) NavHost เป็นส่วนประกอบที่จำเป็นสำหรับแอปพลิเคชัน Compose ใดๆ ที่มีการนำทาง ภายใน NavHost เส้นทาง composable จะถูกลงทะเบียนพร้อมกับอาร์กิวเมนต์เสริม ดีพลิงก์ และแอนิเมชัน แต่ละเส้นทางคือฟังก์ชัน composable ทั่วไปที่รับ NavBackStackEntry พร้อมข้อมูลการเปลี่ยนภาพ NavHost จะจัดการปุ่มย้อนกลับ การบันทึกสถานะ และการกู้คืนเมื่อกำหนดค่าใหม่โดยอัตโนมัติ

ประเด็นสำคัญ

  • NavHost — คอนเทนเนอร์ composable ที่เชื่อมโยง NavController กับกราฟเส้นทางและเรนเดอร์หน้าจอปัจจุบัน
  • composable() — ฟังก์ชันสำหรับลงทะเบียนเส้นทางพร้อมกับเส้นทาง อาร์กิวเมนต์ ดีพลิงก์ และแอนิเมชันการเปลี่ยนภาพ
  • startDestination — เส้นทางเริ่มต้นที่เปิดเมื่อสร้าง NavHost
  • อาร์กิวเมนต์ ถูกกำหนดผ่าน navArgument กับ NavType สำหรับการถ่ายโอนข้อมูลแบบกำหนดชนิดระหว่างหน้าจอ
  • แอนิเมชัน ถูกกำหนดค่าแบบทั่วโลกหรือรายบุคคลผ่านพารามิเตอร์ enterTransition, exitTransition

NavHost ใน Jetpack Compose คืออะไร?

NavHost คือฟังก์ชัน composable ที่ให้คอนเทนเนอร์สำหรับแสดงหน้าจอนำทางปัจจุบัน NavHost รับ NavController, startDestination และกราฟเส้นทางที่สร้างขึ้นผ่าน Kotlin DSL เมื่อเส้นทางปัจจุบันเปลี่ยนไป NavHost จะสลับ composable ที่แสดงด้วยแอนิเมชันที่ระบุ

NavHost ทำหน้าที่เป็น ตัวสลับหน้าจอ: มันติดตาม NavBackStackEntry ปัจจุบันจาก NavController และเรนเดอร์บล็อก composable ที่เกี่ยวข้อง แต่ละหน้าจอคือฟังก์ชัน composable อิสระที่รับ NavBackStackEntry พร้อมอาร์กิวเมนต์เส้นทาง หน้าจอทั้งหมดมีอยู่ในแผนผังการประกอบเดียว แต่ NavHost จะแสดงเพียงครั้งละหนึ่งหน้า โดยซ่อนหน้าอื่นๆ ผ่านแอนิเมชัน

ต่างจาก FragmentManager ตรงที่ NavHost ไม่ได้สร้าง Fragment สำหรับแต่ละหน้าจอ วงจรชีวิตทั้งหมดถูกจัดการผ่าน CompositionLifecycle — ฟังก์ชัน composable ไม่มี onStart/onResume ดังนั้น LaunchedEffect และ DisposableEffect จึงถูกใช้สำหรับเอฟเฟกต์ข้างเคียง NavHost สมัครสมาชิก NavController โดยอัตโนมัติและประกอบ UI ใหม่เมื่อเส้นทางเปลี่ยนแปลง

ตามข้อมูลของ Google NavHost เป็น API ที่เสถียรตั้งแต่ Navigation 2.4.0 ตั้งแต่เวอร์ชัน 2.8.0 NavHost รองรับการนำทางแบบ Type-Safe ผ่าน Kotlin Serialization ซึ่งแทนที่เส้นทางสตริงด้วยคลาสข้อมูล NavHost ยังรองรับกราฟแบบซ้อน ซึ่งช่วยให้จัดระเบียบการนำทางตามโมดูลได้

NavHost ถูกสร้างขึ้นด้วยพารามิเตอร์ที่จำเป็นสองตัว: navController (อินสแตนซ์ของ NavHostController) และ startDestination (สตริงเส้นทางของหน้าจอแรก) พารามิเตอร์ที่สามคือบล็อกตัวสร้างที่ลงทะเบียนเส้นทางทั้งหมดผ่าน composable(), navigation() และ dialog()

kotlin
@Composable
fun AppNavHost(navController: NavHostController) {
    NavHost(
        navController = navController,
        startDestination = "home"
    ) {
        composable("home") { HomeScreen(navController) }
        composable("settings") { SettingsScreen(navController) }
    }
}

startDestination คือเส้นทางที่เปิดเมื่อ NavHost เปิดตัวครั้งแรก หากแบ็กสแต็กว่างเปล่า NavHost จะเพิ่ม startDestination ลงในสแตกโดยอัตโนมัติ เมื่อกำหนดค่าใหม่ (หมุนหน้าจอ) NavHost จะกู้คืนเส้นทางล่าสุดจาก savedState ไม่ใช่ startDestination

สำหรับ BottomNavigation startDestination คือหนึ่งในเส้นทางของแผงด้านล่าง เส้นทางแผงที่เหลือจะถูกเพิ่มเป็นรายการ composable แยกต่างหาก NavHost ควรวางไว้ภายใน Scaffold.content — ที่ซึ่งเนื้อหาหลักของแอปพลิเคชันแสดงอยู่ NavHost ใช้พื้นที่ความสูงที่มีอยู่ทั้งหมดลบด้วย TopAppBar และ BottomNavigation

การลงทะเบียนเส้นทางผ่าน composable

ฟังก์ชัน composable(route, arguments, deepLinks, enterTransition, exitTransition, content) ลงทะเบียนเส้นทางในกราฟ NavHost พารามิเตอร์ route คือสตริงที่อธิบายเส้นทางด้วยตัวยึดตำแหน่งเสริมในรูปแบบ {paramName} ตัวยึดตำแหน่งจะถูกแทนที่ด้วยค่าจริงระหว่างการนำทาง

บล็อก content ของ composable รับ NavBackStackEntry ซึ่งใช้ดึงอาร์กิวเมนต์ ฟังก์ชัน composable ของหน้าจอจะถูกเรนเดอร์เฉพาะเมื่อเส้นทาง NavController ปัจจุบันตรงกับเส้นทางเท่านั้น หากไม่ตรงกัน composable จะถูกลบออกจากการประกอบ แต่สถานะของมันสามารถรักษาไว้ได้ผ่าน rememberSaveable หรือ ViewModel กับ SavedStateHandle

kotlin
composable(
    route = "article/{articleId}",
    arguments = listOf(navArgument("articleId") {
        type = NavType.IntType
        defaultValue = 0
    }),
    deepLinks = listOf(navDeepLink { uriPattern = "https://app.example/article/{articleId}" })
) { backStackEntry ->
    val articleId = backStackEntry.arguments?.getInt("articleId") ?: 0
    ArticleScreen(articleId = articleId)
}

จำนวนรายการ composable ภายใน NavHost อาจมีตั้งแต่ไม่กี่รายการไปจนถึงหลายร้อยรายการ สำหรับแอปพลิเคชันขนาดใหญ่ เส้นทางจะถูกแบ่งตามโมดูลและเชื่อมต่อผ่านกราฟแบบซ้อน แต่ละ composable สามารถมีการตั้งค่าแอนิเมชัน ดีพลิงก์ และอาร์กิวเมนต์ของตัวเอง

อาร์กิวเมนต์และพารามิเตอร์เส้นทางแบบกำหนดชนิด

อาร์กิวเมนต์เส้นทางถูกกำหนดผ่านพารามิเตอร์ arguments: List<NamedNavArgument> ใน composable() แต่ละอาร์กิวเมนต์ถูกกำหนดผ่าน navArgument(name) { type; defaultValue } NavType กำหนดชนิดของอาร์กิวเมนต์: StringType, IntType, LongType, FloatType, BoolType, ParcelableType และ ReferenceType

พารามิเตอร์เส้นทางตัวอย่างเส้นทางNavType
เส้นทาง (path)"user/{id}"NavType.IntType
คิวรี (query)"search?q={query}"NavType.StringType
ตัวเลือก"details/{id}?tab={tab}"StringType + defaultValue=""
Parcelable"checkout/{order}"NavType.ParcelableType

อาร์กิวเมนต์ถูกดึงจาก NavBackStackEntry ผ่าน arguments?.getInt("id") สำหรับอาร์กิวเมนต์บังคับ สามารถละ defaultValue ได้ — NavType จะใช้ null สำหรับอาร์กิวเมนต์ตัวเลือก ต้องตั้งค่า defaultValue มิฉะนั้นการนำทางจะโยนข้อยกเว้นหากพารามิเตอร์หายไป

ตั้งแต่ Navigation 2.8.0 แนะนำให้ใช้การนำทางแบบ Type-Safe: กำหนด sealed class หรือ data class สำหรับเส้นทางด้วย Kotlin Serialization แทนที่เส้นทางสตริง ให้ใช้ composable<RouteType> { backStackEntry -> } ซึ่งช่วยขจัดข้อผิดพลาดในการพิมพ์ในเส้นทางและสร้าง NavType สำหรับอาร์กิวเมนต์โดยอัตโนมัติ หากต้องการย้าย ให้เพิ่มการพึ่งพา navigation-compose-typesafe และปลั๊กอิน Kotlin Serialization

กราฟนำทางแบบซ้อน

nested graphs — กลไกสำหรับจัดกลุ่มเส้นทางภายใน NavHost โดยใช้ฟังก์ชัน navigation(route, startDestination) กราฟแบบซ้อนมีคำนำหน้าเส้นทางและ startDestination ของตัวเอง และเส้นทางทั้งหมดสามารถเข้าถึงได้ผ่านคำนำหน้า กราฟแบบซ้อนใช้สำหรับสถาปัตยกรรมแบบโมดูล ซึ่งแต่ละโมดูลคุณสมบัติจะลงทะเบียนกราฟย่อยของตัวเอง

ประโยชน์ของกราฟแบบซ้อน: การแยกเส้นทางภายในโมดูล แบ็กสแต็กแบบรวมสำหรับกลุ่มหน้าจอ และความสามารถในการนำทางตามคำนำหน้าโดยไม่เปิดเผยโครงสร้างภายใน ตัวอย่างเช่น กราฟ "auth" ประกอบด้วย "auth/login" และ "auth/register" การนำทางสามารถทำได้ทั้งผ่านเส้นทางแบบเต็มหรือผ่านคำนำหน้าด้วยการเปลี่ยนเส้นทางไปยัง startDestination

kotlin
NavHost(navController = navController, startDestination = "main") {
    composable("main") { MainScreen(navController) }
    navigation(
        route = "auth",
        startDestination = "auth/login"
    ) {
        composable("auth/login") { LoginScreen(navController) }
        composable("auth/register") { RegisterScreen(navController) }
    }
}

กราฟแบบซ้อนรองรับการส่งอาร์กิวเมนต์ในระดับกราฟ: พารามิเตอร์ที่ประกาศในเส้นทางของกราฟจะถูกส่งไปยังเส้นทางภายในทั้งหมด หากต้องการล้างกราฟแบบซ้อน ให้ใช้ popBackStack(route) — มันจะลบรายการภายในทั้งหมด กราฟแบบซ้อนไม่มีขีดจำกัดความลึก แต่แนะนำไม่เกิน 3 ระดับเพื่อความอ่านง่าย

การปรับแต่งแอนิเมชันและการเปลี่ยนภาพ

NavHost รองรับแอนิเมชันการเปลี่ยนภาพระหว่างเส้นทาง composable ผ่านพารามิเตอร์ enterTransition, exitTransition, popEnterTransition และ popExitTransition แอนิเมชันถูกตั้งค่าครั้งเดียวสำหรับ NavHost และนำไปใช้กับทุกเส้นทาง หรือเป็นรายบุคคลสำหรับแต่ละ composable โดยค่าเริ่มต้น แอนิเมชันจะถูกปิดใช้งาน

การกำหนดค่าทั่วไป: enterTransition = slideInHorizontally(initialOffsetX = { it }) — หน้าจอเลื่อนเข้ามาจากด้านขวา; exitTransition = slideOutHorizontally(targetOffsetX = { -it }) — หน้าจอเลื่อนออกไปทางด้านซ้าย สำหรับแอนิเมชัน pop ทิศทางจะกลับด้าน: หน้าจอเลื่อนเข้ามาจากด้านซ้ายและเลื่อนออกไปทางด้านขวา สำหรับ BottomNavigation ใช้ fadeIn/fadeOut โดยไม่มีการเลื่อน

kotlin
NavHost(
    navController = navController,
    startDestination = "home",
    enterTransition = { slideInHorizontally(initialOffsetX = { it }) + fadeIn() },
    exitTransition = { slideOutHorizontally(targetOffsetX = { -it }) + fadeOut() },
    popEnterTransition = { slideInHorizontally(initialOffsetX = { -it }) + fadeIn() },
    popExitTransition = { slideOutHorizontally(targetOffsetX = { it }) + fadeOut() }
) { /* composable routes */ }

แอนิเมชันแบบกำหนดเองถูกสร้างขึ้นโดยใช้ Compose Animation API: AnimatedContentTransitionScope ให้การเข้าถึงมิติของคอนเทนเนอร์ ความคืบหน้าของแอนิเมชัน และทิศทาง สำหรับการเปลี่ยนภาพองค์ประกอบที่ใช้ร่วมกัน (องค์ประกอบหนึ่งย้ายไปยังอีกหน้าจอหนึ่งอย่างราบรื่น) จำเป็นต้องใช้ไลบรารี Accompanist Navigation Animation หรือการนำไปใช้แบบกำหนดเองผ่าน sharedElement Modifier ตามข้อมูลของ Android Developers (2025) แอนิเมชันเลื่อนเริ่มต้น (เข้าจากด้านขวา ออกทางด้านซ้าย) ถูกใช้ใน 80% ของแอปพลิเคชัน Android ที่มีการนำทาง

คำถามที่พบบ่อย

สามารถใช้ NavHost หลายตัวใน Activity เดียวกันได้หรือไม่?

ในทางเทคนิคได้ แต่ไม่แนะนำ แต่ละ NavHost สร้างแบ็กสแต็กอิสระ ซึ่งทำลายการนำทางแบบรวม ข้อยกเว้นคือพื้นที่แยกกัน เช่น NavHost สำหรับเนื้อหาหลักและ NavHost สำหรับ BottomSheet ที่มีการนำทางของตัวเอง

NavHost แตกต่างจาก Scaffold ใน Compose อย่างไร?

NavHost คือคอนเทนเนอร์นำทางที่สลับหน้าจอ Scaffold คือเค้าโครงของทั้งหน้า (TopAppBar, BottomNavigation, FloatingActionButton) โดยทั่วไป NavHost จะถูกวางไว้ภายใน Scaffold.content Scaffold ไม่ได้จัดการการนำทาง มันเพียงให้ช่องสำหรับส่วนประกอบ UI

จะแชร์ ViewModel ระหว่างหน้าจอผ่าน NavHost ได้อย่างไร?

ViewModel ถูกสร้างขึ้นภายใน NavBackStackEntry ผ่าน viewModel() หากต้องการแชร์ ViewModel ระหว่างหน้าจอ ให้ใช้ parentNavController: ผูก ViewModel ที่ใช้ร่วมกันกับรายการหลัก ทางเลือกอื่นคือ DI (Hilt/Koin) ที่มีขอบเขต NavGraph

ทำไม NavHost ถึงสร้าง composable ใหม่ทุกครั้งที่มีการนำทาง?

นี่คือพฤติกรรมปกติ — NavHost จะลบ composable ออกจากการประกอบเมื่อออกจากเส้นทาง หากต้องการรักษาสถานะ ให้ใช้ rememberSaveable สำหรับสถานะ UI และ ViewModel กับ SavedStateHandle สำหรับตรรกะทางธุรกิจ

จะเพิ่มการจัดการ 404 (เส้นทางไม่รู้จัก) ใน NavHost ได้อย่างไร?

เพิ่มเส้นทางสุดท้าย composable("404") และนำทางไปยังเส้นทางนั้นเมื่อได้รับดีพลิงก์ที่ไม่รู้จัก NavHost ไม่มีเส้นทาง catch-all — ตรวจสอบเส้นทางในตัวจัดการอินเทนต์ดีพลิงก์ก่อน navigate() หากไม่พบเส้นทาง ให้นำทางไปที่ 404

สรุป

  • NavHost — คอนเทนเนอร์ composable ของ Navigation Compose ที่เชื่อมโยง NavController กับกราฟเส้นทางและเรนเดอร์หน้าจอปัจจุบัน
  • composable() ลงทะเบียนเส้นทางพร้อมกับเส้นทาง อาร์กิวเมนต์ (NavType) ดีพลิงก์ และแอนิเมชัน
  • startDestination — เส้นทางเริ่มต้นที่เปิดเมื่อ NavHost เปิดตัวครั้งแรก
  • อาร์กิวเมนต์ ถูกส่งผ่านตัวยึดตำแหน่ง {param} กับ NavType สำหรับการกำหนดชนิดและ defaultValue สำหรับพารามิเตอร์ตัวเลือก
  • กราฟแบบซ้อน ผ่าน navigation() อนุญาตให้จัดกลุ่มเส้นทางตามโมดูลด้วยแบ็กสแต็กที่แยกออกจากกัน
  • แอนิเมชัน ของการเปลี่ยนภาพถูกกำหนดค่าผ่าน enterTransition/exitTransition โดยใช้ Compose Animation API
  • NavHost จัดการปุ่มย้อนกลับ การบันทึกสถานะ และดีพลิงก์โดยอัตโนมัติโดยไม่ต้องใช้โค้ดเพิ่มเติม

เราจะพัฒนาแอปพลิเคชันบนมือถือแบบครบวงจร

IT Sectr สร้างแอปพลิเคชัน iOS และ Android สำหรับสตาร์ทอัพและธุรกิจตั้งแต่ปี 2017 เราจะให้คำแนะนำและเสนอวิธีแก้ปัญหาที่ดีที่สุดแก่คุณ

ปรึกษาโครงการ

อ่านเพิ่มเติม