0Pricing
Android Academy · 课时

为什么要模块化

提升构建速度,明确归属并实现复用

为什么要模块化 是 CoddyKit 上的免费 Android Academy 课时。 这是第 1 节课,共 4 节。 你可以在下方免费阅读本课时的完整内容 — 然后在浏览器中使用内置代码编辑器和全天候 AI 导师进行实践。 这是 Android Academy 学习路径的一部分,你的进度在网页和 CoddyKit 应用中同步。 Android Academy 课程共包含 4 节课。

单体应用的问题

随着 Android 应用不断发展,其全部代码往往都位于单个 app 模块中。这就是单体应用。起初这样很方便,但随着时间推移会变得越来越难以维护:每次更改都会涉及同一个模块,构建速度会变慢,团队成员也经常互相造成干扰。

模块化是指将这一个大型模块拆分为许多更小、职责更集中的 Gradle 模块。在本课中,您将了解团队这样做的原因,以及它带来的具体好处。

模块究竟是什么

在 Gradle 中,模块是一个可以独立构建的代码单元,并拥有自己的 build.gradle.kts 文件。您的应用已经至少有一个模块::app 模块。您需要在 settings.gradle.kts 中声明每个模块。

添加模块非常简单,只需将其包含进来即可。每个模块都会生成自己的构建输出,并且可以依赖其他模块。

// settings.gradle.kts
include(":app")
include(":core:designsystem")
include(":core:data")
include(":feature:home")
include(":feature:profile")

好处 1:更快的构建速度

最明显的实际收益是构建速度。Gradle 可以并行构建模块,更重要的是,还能缓存并跳过输入未发生变化的模块。

如果您只编辑了 :feature:profile,Gradle 就会复用其他模块已经构建好的输出。在单体应用中,任何更改都可能迫使整个应用重新编译。

  • 跨模块并行执行
  • 增量构建:只重新构建发生变化的部分
  • 提高远程缓存和构建缓存的命中率
// gradle.properties
org.gradle.parallel=true
org.gradle.caching=true
org.gradle.configuration-cache=true

好处 2:清晰的边界

模块会强制建立边界。一个模块中的代码只能访问另一个模块有意公开的内容。这样可以避免代码纠缠成一团、每个类都访问其他所有类的混乱局面。

您可以通过 Gradle 的 api 与 implementation 配置控制可见性。implementation 会将依赖限制在模块内部,使用者无法意外使用它。

// feature/profile/build.gradle.kts
dependencies {
    // Exposed to whoever depends on :feature:profile
    api(project(":core:model"))

    // Private: hidden from consumers of this module
    implementation(project(":core:network"))
}

好处 3:复用

将逻辑放入职责集中的模块后,您可以在任何地方复用它。包含主题、颜色和可复用组合项的 :core:designsystem 模块可以被每个功能模块共享。

同样的思路也适用于多个应用:公司可以在多个产品之间共享 :core:network 模块,而不必复制代码。

// Any feature can pull in shared building blocks
// feature/home/build.gradle.kts
dependencies {
    implementation(project(":core:designsystem"))
    implementation(project(":core:data"))
}

好处 4:团队负责制

模块与团队负责范围能够很好地对应。支付团队负责 :feature:payments;个人资料团队负责 :feature:profile。由于代码位于不同的文件夹和构建文件中,他们可以并行工作,并减少合并冲突。

借助 CODEOWNERS 文件等工具,系统可以根据模块路径自动向正确的团队发起审查请求。

# .github/CODEOWNERS
/feature/payments/   @org/payments-team
/feature/profile/    @org/profile-team
/core/designsystem/  @org/platform-team

好处 5:通过可见性实现封装

在模块内部,Kotlin 的 internal 修饰符非常强大。internal 类或函数仅在其所属模块内可见。其他模块根本无法引用它。

这样,您就可以公开一个较小的公共接口,同时隐藏实现细节;而在单个巨型模块中,这是无法强制实现的。

// In :core:data
// Public API other modules may use
fun interface UserRepository {
    suspend fun loadUser(id: String): User
}

// Hidden from other modules
internal class DefaultUserRepository(
    private val api: UserApi
) : UserRepository {
    override suspend fun loadUser(id: String) = api.fetch(id).toUser()
}

代价:额外的开销

模块化并非没有代价。每个模块都需要维护一个 build.gradle.kts,您还必须考虑每段代码应归哪个模块负责。对一个很小的应用过度模块化,只会增加杂务,却没有实际收益。

经验法则是:当构建时间令人难以忍受、团队之间频繁发生冲突,或您拥有明确可复用的层时,再进行模块化。周末业余制作的应用通常不需要 30 个模块。

典型的模块布局

一种常见且可扩展的结构,是将模块分为 app、feature 和 core 层。:app 模块负责将所有内容连接起来;功能模块包含面向用户的界面;核心模块包含共享基础设施。

// Conceptual project tree
// app/                  <- single entry point, wires features
// feature/
//   home/
//   profile/
//   settings/
// core/
//   designsystem/       <- theme + reusable composables
//   data/               <- repositories
//   network/            <- Retrofit/Ktor
//   model/              <- shared data classes

约定插件让结构保持简洁

模块数量较多时,在各处复制粘贴相同的 Gradle 配置是一个陷阱。团队会将共享配置提取到约定插件中(位于 build-logic 模块)。这样,每个实际模块只需应用一个插件,而不必重复几十行配置。

您会在 Now in Android 等大型开源应用中看到这种模式。现在您只需了解其目标:让构建文件保持简短且一致。

// feature/home/build.gradle.kts
plugins {
    // One convention plugin sets up Android + Compose + Kotlin
    id("myapp.android.feature")
}

android { namespace = "com.myapp.feature.home" }

思维方式:用分层的方式思考

最有用的心智模型是:依赖关系应当向下流动。功能模块依赖核心模块;核心模块不依赖功能模块。:app 模块位于最顶层,依赖于组装应用所需的一切。

如果您始终保持这个方向,模块图就会保持整洁,也能避免循环依赖;您将在后续课程中进一步探索这一点。

// Allowed:  app -> feature -> core
// Forbidden: core -> feature (upward) or feature -> feature (sideways)
// app/build.gradle.kts
dependencies {
    implementation(project(":feature:home"))
    implementation(project(":feature:profile"))
}

快速检查

对于不断增长的 Android 应用,团队通过模块化能够获得的最具体、最日常的好处是什么?

总结:为什么要模块化

您已经了解了团队将单体应用拆分为模块的原因:

  • 通过并行执行和增量缓存实现更快的构建速度
  • 使用 api/implementation 和 internal 建立清晰的边界
  • 复用设计系统、网络等核心层
  • 通过团队负责制减少合并冲突

您还了解了这样做的代价(额外的构建文件)以及黄金法则:依赖关系向下流动,即 app -> feature -> core。接下来,您将绘制功能模块与核心模块之间的实际边界。

常见问题解答

「为什么要模块化」课时是免费的吗?

是的 — 「为什么要模块化」的完整文本可在网页上免费阅读。要进行交互式练习(内置代码编辑器和全天候 AI 导师)并解锁 Android Academy 课程的其余内容,请升级到 CoddyKit PRO。 Android Academy 课程共包含 4 节课。

「为什么要模块化」这节课中我会学到什么?

提升构建速度,明确归属并实现复用 你通过在浏览器中直接运行的动手代码来练习 Android Academy,全天候 AI 导师会在你学习这节课的过程中回答你的问题。

学习 Android Academy 需要有经验吗?

无需任何先前经验。CoddyKit 上的 Android Academy 课程适合初学者到高级学习者,你可以从这里开始或从头开始,按照自己的节奏学习。 这是第 1 节课,共 4 节。

「为什么要模块化」课时需要多长时间?

大多数 CoddyKit 课程大约需要 5–10 分钟。每节课都很精短且互动,所以你能稳步进步,并在网页和应用中从离开的地方继续。

我能在这节 Android Academy 课中编写并运行代码吗?

能。每节 Android Academy 课都包含内置代码编辑器,你可以在浏览器中直接编写并运行真实代码,并获得即时 AI 反馈 — 无需本地设置。

此课程中的所有课时

  1. 为什么要模块化
  2. 功能模块与核心模块
  3. 管理模块依赖
  4. 跨模块导航
← 返回 Android Academy