为什么要模块化
提升构建速度,明确归属并实现复用
为什么要模块化 是 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 反馈 — 无需本地设置。