You need to enable JavaScript to run this app. 如何从app或其他动态功能模块跳转至动态功能模块内的Jetpack Compose函数
优惠活动
大模型
产品
解决方案
定价
更多

如何从app或其他动态功能模块跳转至动态功能模块内的Jetpack Compose函数

方案结论

完全存在不需要依赖Fragment作为中间目的地的纯Compose动态功能模块导航方案,Jetpack Navigation官方已经提供了原生支持,核心依赖DynamicNavHost + 公共路由契约 + SPI服务发现即可实现,无需app模块直接感知动态功能模块的内部实现。


1. 前置依赖配置

在项目根目录的公共基础模块(所有模块都依赖的纯Kotlin/Java模块,无业务逻辑)、app宿主模块、所有动态功能模块中引入导航依赖:

// 模块级build.gradle.kts
dependencies {
    implementation "androidx.navigation:navigation-compose:2.7.5"
    implementation "androidx.navigation:navigation-dynamic-features-compose:2.7.5"
    // 可选:如果用Safe Args生成路由类
    implementation "androidx.navigation:navigation-safe-args-gradle-plugin:2.7.5"
}

2. 公共路由契约层定义

在公共基础模块中定义全局路由常量、参数规范和导航注册接口,避免各模块直接依赖:

// 公共模块中定义
object RouteConstants {
    const val MAIN_ROUTE = "main"
    const val LOGIN_ROUTE = "login"
    const val STAGE_ROUTE = "stage"
    // 跳转参数常量
    const val ARG_USER_SESSION = "sessionArgs"
}

// 导航注册接口,所有动态模块实现该接口注册自己的导航图
interface NavigationProvider {
    fun registerNavGraph(navGraphBuilder: NavGraphBuilder, navController: NavHostController)
}

3. 动态功能模块实现导航注册

以login动态功能模块为例,实现导航注册接口,注册自身的Compose目的地:

// login模块中
@AutoService(NavigationProvider::class) // 用Google AutoService做SPI服务注册
class LoginNavigationProvider : NavigationProvider {
    override fun registerNavGraph(navGraphBuilder: NavGraphBuilder, navController: NavHostController) {
        navGraphBuilder.composable(RouteConstants.LOGIN_ROUTE) {
            LoginPage(
                onLoginSuccess = { userSession ->
                    // 跨模块跳转到stage模块,直接用公共路由即可,不需要依赖stage模块
                    navController.navigate("${RouteConstants.STAGE_ROUTE}?${RouteConstants.ARG_USER_SESSION}=${userSession}")
                }
            )
        }
    }
}

stage模块的实现逻辑和login模块完全一致,自行注册自身的Compose目的地即可。

4. app宿主模块初始化导航

app模块使用DynamicNavHost替代普通NavHost,通过SPI加载所有动态模块的导航注册实现,完成全局导航图构建:

// app模块的主Activity中
class MainActivity : ComponentActivity() {
    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContent {
            val navController = rememberDynamicNavHostController()
            DynamicNavHost(
                navController = navController,
                startDestination = RouteConstants.MAIN_ROUTE
            ) {
                // 先注册app模块自身的目的地
                composable(RouteConstants.MAIN_ROUTE) {
                    MainPage(
                        onGoToLogin = {
                            // 直接导航到login模块的路由,不需要感知login模块内部实现
                            navController.navigate(RouteConstants.LOGIN_ROUTE)
                        }
                    )
                }

                // SPI加载所有动态模块的导航注册实现,批量注册
                val navProviders = ServiceLoader.load(NavigationProvider::class.java)
                navProviders.forEach { provider ->
                    provider.registerNavGraph(this, navController)
                }
            }
        }
    }
}

注意事项

如果动态功能模块未提前安装,导航前需要先通过Play Core API查询模块安装状态,触发下载安装完成后再执行导航操作,避免路由找不到的异常。

内容的提问来源于stack exchange,提问作者Thracian

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.10.08 04:45:02