多模块项目架构
源:Android 官方文档 - Projects overview
多模块项目通过将应用拆分为多个独立模块,实现代码复用、加快构建速度和强制模块边界。
模块类型
Application 模块
应用的入口点,包含应用级代码和资源。
kotlin
// app/build.gradle.kts
plugins {
id("com.android.application")
}
android {
namespace = "com.example.myapp"
defaultConfig {
applicationId = "com.example.myapp"
}
}
dependencies {
implementation(project(":core"))
implementation(project(":feature-login"))
}特点:
- 每个项目只能有一个 application 模块
- 生成 APK/AAB
- 定义 applicationId
Library 模块
可复用的代码库,可被多个模块依赖。
kotlin
// core/build.gradle.kts
plugins {
id("com.android.library")
}
android {
namespace = "com.example.core"
}
dependencies {
api("androidx.core:core-ktx:1.15.0")
}特点:
- 生成 AAR 文件
- 可被其他模块依赖
- 不能独立运行
Dynamic Feature 模块
按需下载的功能模块,减小初始安装体积。
kotlin
// feature-camera/build.gradle.kts
plugins {
id("com.android.dynamic-feature")
}
android {
namespace = "com.example.feature.camera"
}
dependencies {
implementation(project(":app"))
}在 app 模块中声明:
kotlin
// app/build.gradle.kts
android {
dynamicFeatures += setOf(":feature-camera", ":feature-gallery")
}Test Fixtures 模块 AGP 7.1+
提供测试辅助代码,可在多个模块间共享测试工具。
kotlin
// core/build.gradle.kts
plugins {
id("com.android.library")
id("java-test-fixtures")
}
dependencies {
// 测试辅助代码的依赖
testFixturesImplementation("junit:junit:4.13.2")
}使用:
kotlin
// feature-login/build.gradle.kts
dependencies {
testImplementation(testFixtures(project(":core")))
}模块间依赖
implementation
依赖不传递,推荐用于大多数场景。
kotlin
dependencies {
implementation(project(":core"))
}api
依赖传递,仅在需要暴露传递依赖时使用。
kotlin
// core/build.gradle.kts
dependencies {
api("com.squareup.retrofit2:retrofit:2.9.0") // 暴露给依赖core的模块
}
// app/build.gradle.kts
dependencies {
implementation(project(":core")) // 自动获得 Retrofit 依赖
}路径依赖
kotlin
dependencies {
implementation(project(":libraries:networking"))
implementation(project(":features:login"))
}项目结构示例
按功能分层
MyApp/
├── app/ # Application模块
├── core/ # 核心库
│ ├── common/ # 通用工具
│ ├── network/ # 网络层
│ └── database/ # 数据库
├── features/ # 功能模块
│ ├── login/
│ ├── home/
│ └── profile/
└── libraries/ # 第三方库封装
└── analytics/配置:
kotlin
// settings.gradle.kts
include(":app")
include(":core:common")
include(":core:network")
include(":core:database")
include(":features:login")
include(":features:home")
include(":features:profile")
include(":libraries:analytics")按层次分层
MyApp/
├── app/ # UI层
├── domain/ # 业务逻辑层
├── data/ # 数据层
└── presentation/ # 展示层约定插件(Convention Plugins)
创建可复用的构建逻辑,避免重复配置。
创建约定插件
创建 buildSrc 模块:
MyApp/
└── buildSrc/
├── build.gradle.kts
└── src/main/kotlin/
├── AndroidLibraryConventionPlugin.kt
└── AndroidFeatureConventionPlugin.ktbuildSrc/build.gradle.kts:
kotlin
plugins {
`kotlin-dsl`
}
dependencies {
implementation("com.android.tools.build:gradle:8.7.3")
implementation("org.jetbrains.kotlin:kotlin-gradle-plugin:2.1.0")
}AndroidLibraryConventionPlugin.kt:
kotlin
import com.android.build.gradle.LibraryExtension
import org.gradle.api.Plugin
import org.gradle.api.Project
import org.gradle.kotlin.dsl.configure
class AndroidLibraryConventionPlugin : Plugin<Project> {
override fun apply(target: Project) {
with(target) {
with(pluginManager) {
apply("com.android.library")
apply("org.jetbrains.kotlin.android")
}
extensions.configure<LibraryExtension> {
compileSdk = 34
defaultConfig {
minSdk = 24
}
compileOptions {
sourceCompatibility = JavaVersion.VERSION_17
targetCompatibility = JavaVersion.VERSION_17
}
}
}
}
}使用约定插件
kotlin
// core/build.gradle.kts
plugins {
id("android-library-convention") // 使用约定插件
}
android {
namespace = "com.example.core"
}Composite Build
将多个独立项目组合在一起,适合大型项目或多团队协作。
配置 Composite Build
kotlin
// settings.gradle.kts
includeBuild("../shared-library")
includeBuild("../common-utils")
include(":app")
include(":feature-login")使用 includedBuild 依赖
kotlin
// app/build.gradle.kts
dependencies {
implementation("com.example:shared-library:1.0.0") // 来自 includedBuild
}依赖管理最佳实践
Version Catalog 集中管理
toml
# gradle/libs.versions.toml
[versions]
kotlin = "2.1.0"
retrofit = "2.9.0"
[libraries]
retrofit = { group = "com.squareup.retrofit2", name = "retrofit", version.ref = "retrofit" }
retrofit-converter-gson = { group = "com.squareup.retrofit2", name = "converter-gson", version.ref = "retrofit" }
[bundles]
retrofit = ["retrofit", "retrofit-converter-gson"]使用:
kotlin
dependencies {
implementation(libs.bundles.retrofit)
}避免循环依赖
❌ 错误示例:
app -> core -> utils -> core # 循环依赖✅ 正确方式:
app -> core -> utils
-> common模块化策略
按功能模块化
优点:
- 清晰的功能边界
- 便于团队分工
- 支持动态交付
示例:
:features:login
:features:home
:features:settings按层次模块化
优点:
- 强制分层架构
- 避免跨层调用
- 便于单元测试
示例:
:presentation
:domain
:data混合模块化
结合功能和层次,适合大型项目。
:app
:features:login:ui
:features:login:domain
:features:login:data
:core:network
:core:database构建优化
使用 Gradle 并行编译
properties
# gradle.properties
org.gradle.parallel=true
org.gradle.caching=true
org.gradle.configureondemand=true减少模块依赖
- 避免不必要的
api依赖 - 使用
implementation代替api - 定期检查依赖树
bash
./gradlew :app:dependencies增量编译
合理划分模块,修改单个模块时仅重新编译相关模块。
测试多模块项目
共享测试代码
使用 Test Fixtures:
kotlin
// core/build.gradle.kts
plugins {
id("java-test-fixtures")
}
// feature-login/build.gradle.kts
dependencies {
testImplementation(testFixtures(project(":core")))
}模块间集成测试
kotlin
// app/build.gradle.kts
dependencies {
androidTestImplementation(project(":core"))
androidTestImplementation(project(":feature-login"))
}最佳实践
明确模块边界:
- 定义清晰的模块职责
- 避免模块间紧耦合
- 使用接口定义模块契约
合理拆分粒度:
- 避免过度拆分(管理成本高)
- 避免拆分不足(编译慢)
- 根据团队规模调整
依赖方向一致:
- 低层模块不依赖高层模块
- 业务模块不依赖UI模块
- 定义清晰的依赖层级
使用约定插件:
- 提取common配置
- 统一编译选项
- 简化模块配置
监控构建时间:
- 使用 Build Analyzer
- 定期检查模块依赖
- 优化慢速模块