为什么要收口导航
老项目里,页面跳转散落在各处:谁都能 startActivity、传 Intent extra,跳转关系靠人肉维护。一旦要改个流程,要翻遍代码。Jetpack Navigation 把所有跳转收口成一张导航图,谁能去哪、带什么参数,一目了然。
导航即图:所有页面跳转声明在一处,跳转关系可读、可查、可重构。
这篇把单 Activity 下的 Navigation 讲透。
单 Activity 架构
单 Activity 架构就是只留一个 MainActivity,其余页面都是 Fragment。Fragment 由 NavHost 承载,导航切换 Fragment。好处是共享同一套 Activity 级状态与工具栏,回退栈由系统统一管理。
<NavHostFragment
android:id="@+id/navHost"
app:navGraph="@navigation/main_nav" />
布局里放一个 NavHostFragment,挂着导航图。
导航图 NavGraph
导航图是一个 XML,声明所有目的地(destination)和它们之间的连接(action)。起始目的地是应用进入的第一个页面。所有页面的进出关系都在这一个文件里。
- destination一个页面(Fragment)。
- action页面之间的跳转。
- startDestination起始页。
- navOptions转场与回退行为。
目的地与动作
每个目的地用 id 标识,跳转动作用 action 连接。代码里跳转不再手写 Intent,而是调 navigate(resId),resId 就是动作 id。
带参数跳转
传参数用 SafeArgs 或 Bundle。导航图里声明参数类型与默认值,编译期生成对应类,跳转时类型安全。比 Intent extra 强在:参数有类型、有默认值、跳转时编译器帮你检查。
底部栏与抽屉的连接
底部导航栏点哪一项,就 navigate 到对应目的地。Navigation 与 BottomNavigationView 配合,选中态与当前目的地自动同步,不用自己监听。
全局动作与深链接
全局动作把多个页面共用的跳转提出来,比如退出登录回到登录页。深链接则让外部 URL 直接落到某个目的地,适合推送跳转、营销落地。
- 跳转关系集中在导航图里。
- 回退栈由系统统一管理。
- 深链接让外部直达指定页。
实战:一个登录到首页的导航
登录成功后导航到首页,登录页从回退栈移除。
findNavController().navigate(
R.id.action_login_to_home,
null,
navOptions { popUpTo(R.id.login) { inclusive = true } }
)
inclusive=true 把登录页一并弹出,用户按返回不会回到登录。导航做到这份上,页面跳转就从散弹枪变成了一张可维护的图。