如何为动态特性模块配置Jetpack Compose Navigation?
一、依赖配置
确保主模块和所有动态特性模块(DFM1/DFM2/DFM3)都添加以下导航相关依赖,重点引入动态特性支持库:
// 各模块build.gradle.kts中的dependencies块 dependencies { // Compose Navigation核心库 implementation("androidx.navigation:navigation-compose:2.7.7") // 动态特性导航支持库 implementation("androidx.navigation:navigation-dynamic-features-compose:2.7.7") }
同时主模块需在android块中声明动态特性模块:
android { // ...其他配置 dynamicFeatures = listOf(":DFM1", ":DFM2", ":DFM3") }
二、主模块导航图配置
主模块作为导航入口,用Kotlin DSL构建包含动态目的地的全局导航图:
@Composable fun MainNavGraph(navController: NavHostController) { NavHost( navController = navController, startDestination = "main_home" ) { // 主模块自有目的地 composable("main_home") { HomeScreen( toDFM1 = { navController.navigate("dfm1_entry") }, toDFM2 = { navController.navigate("dfm2_entry") }, toDFM3 = { navController.navigate("dfm3_entry") } ) } // 注册DFM1的动态目的地 dynamicComposable( route = "dfm1_entry", moduleName = "DFM1" // 需与build.gradle中声明的模块名一致 ) { backStackEntry -> // 加载DFM1内部的子导航图 DFM1NavGraph(navController, backStackEntry) } // DFM2、DFM3的动态目的地注册逻辑同上 dynamicComposable( route = "dfm2_entry", moduleName = "DFM2" ) { backStackEntry -> DFM2NavGraph(navController, backStackEntry) } dynamicComposable( route = "dfm3_entry", moduleName = "DFM3" ) { backStackEntry -> DFM3NavGraph(navController, backStackEntry) } } }
三、动态特性模块内部导航实现
每个DFM需独立构建自身的子导航图,对外暴露可组合函数供主模块调用,以DFM1为例:
@Composable fun DFM1NavGraph(navController: NavHostController, parentBackStackEntry: NavBackStackEntry) { NavHost( navController = navController, startDestination = "dfm1_home", navBackStackEntry = parentBackStackEntry // 绑定主模块传递的返回栈条目,保证导航状态一致 ) { composable("dfm1_home") { DFM1HomeScreen( toDetail = { navController.navigate("dfm1_detail") }, backToMain = { navController.popBackStack() }, toDFM2 = { navController.navigate("dfm2_entry") } ) } composable("dfm1_detail") { DFM1DetailScreen( backToHome = { navController.popBackStack() } ) } } }
DFM2、DFM3的子导航图实现逻辑完全一致,仅需替换路由和对应界面组件。
四、模块间跳转逻辑
1. 主模块跳转DFM
在主模块界面中触发导航即可,比如主模块的HomeScreen:
@Composable fun HomeScreen( toDFM1: () -> Unit, toDFM2: () -> Unit, toDFM3: () -> Unit ) { Column( modifier = Modifier.fillMaxSize(), verticalArrangement = Arrangement.Center, horizontalAlignment = Alignment.CenterHorizontally ) { Button(onClick = toDFM1) { Text("进入DFM1") } Button(onClick = toDFM2) { Text("进入DFM2") } Button(onClick = toDFM3) { Text("进入DFM3") } } }
2. DFM之间互相跳转
直接通过主导航控制器调用目标DFM的路由即可,比如DFM1跳转到DFM2:
// 在DFM1的某界面中 Button(onClick = { navController.navigate("dfm2_entry") }) { Text("从DFM1跳转至DFM2") }
3. DFM返回主模块
调用popBackStack()即可回到主模块的上一个目的地:
Button(onClick = { navController.popBackStack() }) { Text("返回主模块") }
五、核心注意事项
dynamicComposable的moduleName必须与build.gradle中声明的动态模块名完全匹配,否则无法正确加载模块。- DFM的子导航图必须绑定主模块传递的
parentBackStackEntry,避免导航状态混乱。 - 如需传递参数,可在路由中添加占位符(如
"dfm1_entry/{userId}"),通过navBackStackEntry.arguments?.getString("userId")获取参数值。 - 首次跳转未安装的DFM时,系统会自动触发模块下载,可通过
navController.currentBackStackEntry?.destination?.isDynamic判断加载状态,添加加载UI提示。
内容的提问来源于stack exchange,提问作者Chetan Urmaliya
相关产品推荐
相关产品推荐

