Navigation组件基础:Jetpack Navigation核心概念、NavHost/NavController、图导航与深层链接
在 SystemUI 面板中,导航的复杂性随状态栏、通知面板、快速设置、多用户切换等组件的交互而急剧上升。Jetpack Navigation 提供了一套声明式的导航框架,能够以「导航图」为中心统一管理 Fragment 或 Compose 目标之间的跳转、参数传递与回退栈,并原生支持深层链接。本章将深入剖析其核心概念与实现机制,为后续在 SystemUI 中集成 Navigation 打下基础。
3.1 核心概念一览
| 概念 | 作用 | 类比 |
|---|---|---|
| NavController | 导航控制器,管理目标切换、回退栈、参数与深层链接 | 浏览器的“前进/后退”引擎 |
| NavHost | 承载导航图并为 NavController 提供容器视图 | HTML 中的 <router-view> |
| NavGraph | XML 声明的导航图,定义所有可导航的目标及其关系 | 地铁线路图 |
| Destination | 导航图中的一个节点(Fragment / Activity / Compose) | 地铁站 |
| DeepLink | 通过 URL / Intent / PendingIntent 直接跳转到特定目标 | 直达电梯 |
3.2 NavHost 与 NavController 的实现流程
在 SystemUI 面板中,通常使用 FragmentContainerView 作为 NavHost。核心实现步骤:
- 在布局文件中声明
androidx.navigation.fragment.NavHostFragment并绑定导航图。 - 通过
NavHostFragment.findNavController(…)获取 NavController 实例。 - 调用
navController.navigate(R.id.action_xxx)执行页面跳转。 - 通过
navController.navigateDeepLink()处理深层链接。
// 布局文件 fragment_main.xml
<androidx.fragment.app.FragmentContainerView
android:id="@+id/nav_host"
android:name="androidx.navigation.fragment.NavHostFragment"
android:layout_width="match_parent"
android:layout_height="match_parent"
app:navGraph="@navigation/nav_graph_main" />
// 在 Fragment 中获取 NavController
NavController navController = NavHostFragment.findNavController(
requireActivity().findViewById(R.id.nav_host));
navController.navigate(R.id.action_to_quick_settings);
3.3 图导航:Navigation Graph 的结构
导航图使用 XML 定义,位于 res/navigation/ 目录下。每个目标通过 <fragment> 或 <activity> 声明,并用 <action> 定义跳转关系。
<!-- nav_graph_main.xml -->
<?xml version="1.0" encoding="utf-8"?>
<navigation xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
app:startDestination="@id/status_bar_panel">
<fragment
android:id="@+id/status_bar_panel"
android:name="com.android.systemui.StatusBarPanelFragment">
<action
android:id="@+id/action_to_quick_settings"
app:destination="@id/quick_settings_panel" />
<deepLink app:uri="systemui://statusbar" />
</fragment>
<fragment
android:id="@+id/quick_settings_panel"
android:name="com.android.systemui.QuickSettingsFragment" />
</navigation>
3.4 深层链接:从外部唤醒 SystemUI 面板
深层链接允许通过 URI 或 Intent 直接打开导航图中的某个目标,无需经过中间页面。有显式(代码构建)和隐式(XML 声明)两种方式。
| 类型 | 配置位置 | 示例 |
|---|---|---|
| 隐式深层链接 | 在导航图 <deepLink> 中声明 | app:uri="systemui://quick_settings" |
| 显式深层链接 | 代码中动态构建 NavDeepLinkRequest | new NavDeepLinkRequest("systemui://statusbar", null, null) |
处理深层链接时,NavController 会自动匹配 URI 并跳转。在 SystemUI 中,可用于响应全局手势或远程触发通知面板展开。
// 显式深层链接跳转
Uri deepLinkUri = Uri.parse("systemui://quick_settings");
NavDeepLinkRequest request = new NavDeepLinkRequest(deepLinkUri, null, null);
navController.navigate(request);
// 在 AndroidManifest.xml 中声明 Activity 支持深层链接
<activity android:name=".SystemUIActivity">
<intent-filter>
<action android:name="android.intent.action.VIEW" />
<category android:name="android.intent.category.DEFAULT" />
<data android:scheme="systemui" />
</intent-filter>
</activity>
3.5 调试与验证
- Navigation Editor:Android Studio 中可视化编辑导航图,检查动作绑定与参数传递。
- adb 测试深层链接:
adb shell am start -d "systemui://quick_settings" com.android.systemui/.SystemUIActivity - 日志输出:在 NavController 的
addOnDestinationChangedListener中打印目标变化。
navController.addOnDestinationChangedListener((controller, destination, arguments) -> {
Log.d("NavDebug", "当前目标: " + destination.getLabel());
});
3.6 常见错误与避坑
⚠ 未设置 app:startDestination:导航图必须指定 startDestination,否则运行时抛出
⚠ ID 冲突:导航图中的 action ID 和 fragment ID 必须全局唯一,避免与其他资源命名冲突。
⚠ NavHost 容器重复创建:在 Fragment 中使用 NavHostFragment 时,应确保其 id 在宿主 Activity 中唯一且不被替换。
IllegalArgumentException。⚠ ID 冲突:导航图中的 action ID 和 fragment ID 必须全局唯一,避免与其他资源命名冲突。
⚠ NavHost 容器重复创建:在 Fragment 中使用 NavHostFragment 时,应确保其 id 在宿主 Activity 中唯一且不被替换。
3.7 性能与稳定性优化
- 懒加载:对低优先级面板使用
app:popUpTo="@id/root"避免回退栈膨胀。 - 视图重用:尽量使用
ViewStub和FragmentTransaction.setReorderingAllowed(true)减少重建。 - 深层链接超时:为深层链接请求设置
PendingIntent的FLAG_IMMUTABLE(Android 12+)避免序列化异常。 - Safe Args:使用 Safe Args Gradle 插件生成类型安全的参数类,避免运行时类型错误。
📌 核心总结:Jetpack Navigation 通过 NavController + NavHost + NavGraph 三件套,为 SystemUI 提供了可结构化、可调试、支持深层链接的统一导航方案。掌握图的声明方式、Action 连接、深层链接原理,是后续章节实现面板间复杂跳转的基础。