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

Navigation Component跨模块跳转最佳实践咨询

多模块独立Navigation组件跨模块跳转方案

这是安卓多模块开发经过大量项目验证的通用落地方案,无过度设计,可完全实现模块间零耦合,同时适配View、Compose体系下的Navigation组件场景。

核心实现逻辑

核心思路是模块内导航逻辑完全私有,对外只暴露统一路由协议,通过Navigation原生支持的深链接机制完成跳转,全程不需要跨模块依赖页面类、导航资源:

  • 先抽离一个所有业务模块都依赖的公共基础模块common-router,这个模块绝对不依赖任何业务代码,只承担两个职责:
    1. 定义所有跨模块跳转的路由声明,用密封类统一管理路径、参数,避免硬编码路径导致的拼写错误:
    // common-router 模块内代码
    sealed class RoutePath(val path: String) {
        data class OrderDetail(val orderId: String) : RoutePath("order/detail")
        data class UserProfile(val userId: Long) : RoutePath("user/profile")
        // 所有需要对外暴露的跨模块页面,都在这里统一声明
    }
    
    1. 封装统一的跳转入口,业务方不需要自行拼接Uri、处理通用导航逻辑:
    // 全局统一跳转扩展方法,业务方直接调用即可
    fun NavController.navigateTo(route: RoutePath) {
        val uriBuilder = Uri.parse("app://internal/${route.path}").buildUpon()
        // 自动将路由对象的字段拼接为请求参数
        route::class.memberProperties.forEach { prop ->
            uriBuilder.appendQueryParameter(prop.name, prop.get(route).toString())
        }
        // 直接传Uri导航,Navigation组件会自动匹配全应用中声明了对应深链接的页面
        navigate(uriBuilder.build())
    }
    
  • 每个业务模块维护自己的独立Navigation图,只给需要对外暴露的页面配置匹配规则的隐式深链接,配置完全属于模块内部逻辑,其他模块无感知:
    View体系XML导航图配置示例:
    <!-- 订单模块私有navigation xml内的配置 -->
    <fragment
        android:id="@+id/fragment_order_detail"
        android:name="com.xxx.biz.order.OrderDetailFragment">
        <!-- 配置和路由规则匹配的深链接 -->
        <deepLink app:uri="app://internal/order/detail?orderId={orderId}" />
        <argument
            android:name="orderId"
            app:argType="string" />
    </fragment>
    
    Compose Navigation配置示例:
    // 用户模块内部的NavHost配置
    composable(
        route = "internal/user/profile",
        deepLinks = listOf(navDeepLink { uriPattern = "app://internal/user/profile?userId={userId}" }),
        arguments = listOf(navArgument("userId") { type = NavType.LongType })
    ) { backStackEntry ->
        UserProfilePage(backStackEntry.arguments?.getLong("userId"))
    }
    
  • 业务代码调用非常简单,比如首页模块要跳订单详情,不需要依赖订单模块的任何代码,直接写:
    findNavController().navigateTo(RoutePath.OrderDetail(orderId = "ORD20240001"))
    

行业通用避坑准则

  • 绝对禁止跨模块直接引用其他模块的Fragment/Activity类、R.id.xxx_fragment/R.navigation.xxx这类资源ID,只要出现这类硬引用,模块隔离就完全失效,后续模块重构、改包名会触发全量编译报错,维护成本极高。
  • 跨模块跳转只传基础类型、简单可序列化数据,禁止直接传大对象、回调接口,大对象统一通过内存缓存、本地存储传索引key,避免触发TransactionTooLargeException,也防止参数类版本不一致导致类找不到崩溃。
  • 所有全局拦截逻辑(登录态校验、权限校验、路由降级兜底)统一在common-router的跳转入口处处理,不要散落在各个业务页面里,比如跳个人页需要登录,没登录就直接先跳登录页,登录完成后自动续跳目标页,业务模块不需要感知这类公共逻辑。
  • 对外暴露的路由路径做兼容处理,不要随意修改路径、删除参数,必须调整路径时要加映射规则,老路径跳转自动重定向到新路径,避免版本迭代后老的跳转逻辑失效。
  • 不要搞全模块合并的巨型Navigation图,这种做法会把所有模块的导航逻辑强耦合在一起,随着业务扩张XML/路由配置会变得完全不可维护,也失去了多模块拆分支持独立编译、按需加载的意义。
  • 如果需要支持外部H5、系统通知跳原生页面,直接复用这套深链接规则即可,不需要额外做一套路由逻辑,维护成本极低。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.30 04:51:25