Navigation 是 Jetpack 中专门管理 Fragment 跳转与返回栈的组件。它通过声明式导航图(NavGraph)统一管理目标页面、跳转动画、参数传递,彻底告别手写 FragmentTransaction 的繁琐与易错。
一、NavGraph:声明式导航图
在 res/navigation/nav_main.xml 中定义所有目标:
<navigation xmlns:android="http://schemas.android.com/apk/res/android" |
二、NavHostFragment:导航容器
在 Activity 布局中放置 NavHostFragment:
<androidx.fragment.app.FragmentContainerView |
app:defaultNavHost="true" 确保该 NavHostFragment 拦截系统返回键,自动管理返回栈。
三、类型安全的参数传递(Safe Args)
Safe Args 是 Navigation 的 Gradle 插件,在编译期生成类型安全的导航与参数获取代码:
// 跳转并传递参数(Safe Args 生成 Directions 类) |
四、DeepLink 与 BottomNavigation 集成
DeepLink:通过 NavDeepLinkBuilder 构建 PendingIntent 或直接在 NavGraph 中声明 <deepLink>,实现外部 URL 直达应用内页面。
BottomNavigation 集成:
val navController = findNavController(R.id.nav_host_fragment) |
NavigationUI 自动处理 tab 选中状态同步与返回栈管理。需确保 menu item 的 id 与 NavGraph 中 fragment 的 id 保持一致。
五、返回栈高级控制
// 跳转到目标并弹出中间所有页面 |
面试常考问题
Q1:Navigation 与手动 FragmentTransaction 对比优势?
Navigation 提供类型安全的 Safe Args、声明式导航图可视化、内置动画支持、自动处理返回栈与 DeepLink、与 BottomNavigation/DrawerLayout 等 UI 组件无缝集成。减少 XML 布局嵌套和大量 FragmentManager 样板代码。
Q2:NavController 的作用域?
每个 NavHostFragment 有独立的 NavController。通过 findNavController() 获取,Ktx 扩展函数自动按 View 向上查找所属的 NavController。Fragment 的 findNavController() 必须在该 Fragment 位于 NavHostFragment 内时调用才有效。
Q3:如何在 ViewModel 级别驱动导航?
推荐通过 LiveData/StateFlow 暴露导航事件(如 SingleLiveEvent),View 层观察后调用 NavController。避免在 ViewModel 中持有 NavController 引用,保持 ViewModel 对导航框架无感知,便于单元测试。







