You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何为动态特性模块配置Jetpack Compose Navigation?

多模块Jetpack Compose Navigation(Kotlin DSL)结合动态特性模块的实现方案

一、依赖配置

确保主模块和所有动态特性模块(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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.24 07:15:38