news 2026/4/18 6:28:16

Jetpack Compose Navigation 全面使用指南

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
Jetpack Compose Navigation 全面使用指南

🧭 一、为什么需要 Navigation?

在 Compose 中,你不再用Activity 跳转,而是用“声明式导航”

  • 页面 =Composable 函数
  • 跳转 =改变当前“目的地”(Destination)
  • 返回 =从导航栈弹出

Jetpack Compose Navigation 提供了一套统一、安全、带生命周期管理的导航方案。

🛠 二、快速上手:3 步实现页面跳转

第 1 步:添加依赖(build.gradle)

implementation"androidx.navigation:navigation-compose:2.8.0"

第 2 步:定义你的页面(Composable)

@ComposablefunHomeScreen(onNavigateToProfile:()->Unit){Column{Text("首页")Button(onClick=onNavigateToProfile){Text("去个人页")}}}@ComposablefunProfileScreen(){Text("个人中心")}

第 3 步:搭建导航图(NavGraph)

@ComposablefunMyApp(){valnavController=rememberNavController()NavHost(navController=navController,startDestination="home"){composable("home"){HomeScreen{navController.navigate("profile")}}composable("profile"){ProfileScreen()}}}

✅ 效果:点击按钮 → 跳转到个人页!

✅ 返回键自动生效(因为 NavHost 管理了返回栈)

🔑 三、核心概念解析

概念说明
NavController导航控制器,负责跳转、返回等操作
NavHost导航容器,定义所有页面(目的地)
composable(route)声明一个页面,route 是唯一标识(如 “profile”)
导航栈(Back Stack)记录用户访问路径,支持返回

💡 记住:

  • rememberNavController():在 Composable 中获取 NavController
  • 每个 composable 块对应一个页面

📦 四、页面传参(Arguments)

场景:从首页跳转到用户详情页,传userId

✅ 步骤 1:定义带参数的 route
// 使用 {id} 占位符composable("user/{userId}"){backStackEntry->// 从 backStackEntry 获取参数valuserId=backStackEntry.arguments?.getString("userId")?:"unknown"UserDetailScreen(userId=userId)}
✅ 步骤 2:跳转时传值
// 在 HomeScreen 中Button(onClick={navController.navigate("user/123")})

✅ 进阶:类型安全传参(推荐!)

使用 Navigation Safe Args(Compose 版) 或 自定义解析。

方法 A:手动解析(简单场景)
composable("user/{userId}"){entry->valuserId=entry.pathSegments[1]// ["user", "123"]UserDetailScreen(userId)}
方法 B:使用 navArgs + Parcelable(更安全)
// 定义数据类@ParcelizedataclassUserArgs(valid:String,valname:String):Parcelable// 跳转valargs=UserArgs("123","Alice")navController.navigate("user?args=${Uri.encode(args.toString())}")// 不推荐,复杂// 更推荐:直接拼接基础类型navController.navigate("user/${userId}")

📌 官方建议:

对于简单参数(String/Int),直接用 {param};

复杂对象优先通过 ViewModel 共享,而非导航传参。

🔙 五、返回并传递结果(类似 startActivityForResult)

Compose Navigation 原生不支持返回结果,但我们可以用 ViewModel + Shared State 实现。
✅ 推荐方案:共享 ViewModel

// 共享 ViewModel@HiltViewModelclassSharedViewModel@Injectconstructor():ViewModel(){privateval_selectedItem=MutableStateFlow<String?>("")valselectedItem=_selectedItem.asStateFlow()funselectItem(item:String){_selectedItem.value=item}}// 主页@ComposablefunSelectHomeScreen(viewModel:SharedViewModel,onNavigateToSelectItem:()->Unit){valselectedItembyviewModel.selectedItem.collectAsState()Column{Text("选中数据:${selectedItem}")Button(onClick=onNavigateToSelectItem){Text("选项选择")}}}// 选择页@ComposablefunPickerScreen(viewModel:SharedViewModel,onNavigateBackHome:()->Unit){Column{Button(onClick={viewModel.selectItem("选项A")onNavigateBackHome()}){Text("选项A")}}}

✅ 优点:解耦、可测试、支持跨多层返回

💡 注:HiltViewModel 如果没有这个注解,需要引入依赖:

implementation("androidx.hilt:hilt-lifecycle-viewmodel:1.3.0")

🌐 六、深度链接(Deep Link)

让外部链接(如网页、通知)直接打开 App 内页面。

步骤 1:在 composable 中注册 deep link

composable("profile",deepLinks=listOf(navDeepLink{uriPattern="myapp://profile"})){ProfileScreen()}

步骤 2:在 AndroidManifest.xml 中声明

<activityandroid:name=".MainActivity"><intent-filter><actionandroid:name="android.intent.action.VIEW"/><categoryandroid:name="android.intent.category.DEFAULT"/><categoryandroid:name="android.intent.category.BROWSABLE"/><dataandroid:scheme="myapp"android:host="profile"/></intent-filter></activity>

效果:点击 myapp://profile → 直接打开个人页!

🧪 七、测试导航

使用 createAndroidComposeRule + navigate() 模拟跳转。

@TestfuntestNavigateToProfile(){composeTestRule.setContent{MyApp()}// 点击按钮composeTestRule.onNodeWithText("去个人页").performClick()// 验证是否显示个人页内容composeTestRule.onNodeWithText("个人中心").assertExists()}

⚙️ 八、高级技巧

1. 嵌套路由(Nested Graph)

//TODO main是外层的路由路径,home是嵌套内开始展示UI的路由路径navigation(startDestination="home",route="main"){composable("home"){HomeScreen()}composable("settings"){SettingsScreen()}}composable("login"){LoginScreen()}

2. 自定义过渡动画

composable("profile",enterTransition={slideInHorizontally(initialOffsetX={it})},exitTransition={slideOutHorizontally(targetOffsetX={-it})}){...}
3. 拦截返回键
BackHandler(enabled=canExit){navController.popBackStack()}

✅ 十、最佳实践总结

  • 导航图集中管理:所有 composable 定义在一个地方(如 NavGraph.kt)
  • 参数尽量简单:用 ID 代替完整对象
  • 返回结果用共享状态:避免 hack 式回调
  • 深度链接提前规划:方便运营和分享
  • 动画适度使用:提升体验但别过度

🎯 结语

Jetpack Compose Navigation 不只是“页面跳转”,而是一套完整的页面生命周期管理方案。

它帮你处理了:

  • 返回栈
  • 状态保存(配合 rememberSaveable)
  • 深度链接
  • 动画过渡
  • 测试支持

只要掌握NavController+NavHost+composable三件套,你就能构建任意复杂的 App 导航结构!

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/4/12 13:39:16

12种视角魔法:AI图像编辑新革命深度解析

12种视角魔法&#xff1a;AI图像编辑新革命深度解析 【免费下载链接】Qwen-Edit-2509-Multiple-angles 项目地址: https://ai.gitcode.com/hf_mirrors/dx8152/Qwen-Edit-2509-Multiple-angles 还在为单一视角的创意表达而苦恼&#xff1f;今天&#xff0c;让我们一同探…

作者头像 李华
网站建设 2026/4/18 1:57:44

1小时搭建ENSP错误诊断原型系统

快速体验 打开 InsCode(快马)平台 https://www.inscode.net输入框内输入如下内容&#xff1a; 快速开发ENSP诊断原型系统&#xff1a;1. 日志上传接口&#xff08;支持.txt/.log&#xff09;&#xff1b;2. 错误模式识别引擎&#xff08;重点检测40错误特征&#xff09;&#…

作者头像 李华
网站建设 2026/4/18 1:56:10

ROS2 vs ROS1:开发效率对比实测

快速体验 打开 InsCode(快马)平台 https://www.inscode.net输入框内输入如下内容&#xff1a; 创建一个对比测试项目&#xff0c;分别用ROS1 Noetic和ROS2 Humble实现相同的功能&#xff1a;1.建立3个节点的发布-订阅网络&#xff1b;2.测量消息延迟和CPU占用率&#xff1b;3.…

作者头像 李华
网站建设 2026/4/18 1:57:56

24小时开发:基于Sci-Hub的论文推荐系统原型

快速体验 打开 InsCode(快马)平台 https://www.inscode.net输入框内输入如下内容&#xff1a; 快速开发一个论文推荐系统原型&#xff0c;用户输入兴趣领域后&#xff0c;系统从Sci-Hub获取最新论文&#xff0c;基于简单算法推荐相关研究。原型应具备基本UI&#xff0c;展示论…

作者头像 李华
网站建设 2026/4/18 2:02:24

YgoMaster终极指南:免费离线畅玩游戏王大师决斗

YgoMaster终极指南&#xff1a;免费离线畅玩游戏王大师决斗 【免费下载链接】YgoMaster Offline Yu-Gi-Oh! Master Duel 项目地址: https://gitcode.com/gh_mirrors/yg/YgoMaster 想要随时随地享受游戏王大师决斗的乐趣&#xff0c;却苦于网络不稳定或官方服务器限制&am…

作者头像 李华
网站建设 2026/4/18 2:01:29

光纤的制作原理

光纤的制作原理基于光的全反射原理&#xff0c;通过高纯度的玻璃或塑料材料制成纤芯和 包层&#xff0c;利用两者折射率的差异实现光信号的远距离传输。以下是光纤制作的关键步骤 和原理&#xff1a; 一、光纤的基本结构 纤芯&#xff1a;中心部分&#xff0c;折射率较高&#…

作者头像 李华