1. 模块化工程骨架搭建

1.1 模块化架构设计目标

模块化不是简单的文件夹拆分,而是一种编译隔离、职责分离、复用优先的架构方案。在 ViewModel 与模块化搭配场景中,我们需要确保每个模块可独立编译、测试,同时通过 Gradle 统一管理版本,避免依赖地狱。

  • 编译隔离:修改 feature 模块不会触发 core 模块的全量编译。
  • 职责边界:data、domain、presentation 层严格分层,依赖单向。
  • 版本一致:所有第三方库、Kotlin 版本、AGP 版本集中定义,避免升级遗漏。
📌 实践中推荐采用“三层四模块”模式:app(入口)、:feature:*(业务页面)、:lib:core(基础工具)、:lib:data(数据/网络/数据库)。

1.2 Gradle 多模块配置(settings.gradle.kts)

根目录下的 settings.gradle.kts 是模块发现的起点。必须显式声明所有子模块路径,并启用 Version Catalog。

// settings.gradle.kts
pluginManagement {
    repositories {
        google()
        mavenCentral()
        gradlePluginPortal()
    }
}
dependencyResolutionManagement {
    repositoriesMode.set(RepositoriesMode.FAIL_ON_PROJECT_REPOS)
    repositories {
        google()
        mavenCentral()
    }
}

rootProject.name = "ViewModelModularApp"

// 模块注册
include(":app")
include(":feature:login")
include(":feature:home")
include(":lib:core")
include(":lib:data")
include(":lib:network")
include(":lib:test-utils")
💡 模块路径使用冒号分隔层级,例如 :feature:login 对应文件系统 feature/login/ 目录。

1.3 模块命名规范

层级前缀示例职责
应用入口:app:appApplication、Activity、全局依赖注入
业务特征:feature::feature:login页面级 ViewModel、Fragment、导航图
功能库:lib::lib:core基类、扩展函数、通用工具
数据层:lib:data:lib:networkRepository、API 接口、数据库 DAO
测试共享:lib:test-utils:lib:test-utilsMock 数据、测试规则、ViewModel 测试辅助

规范遵循 小写 + 连字符 命名,严禁使用下划线或大写字母。libs.versions.toml 中的依赖别名也需保持一致。

1.4 依赖管理统一版本(Version Catalog)

Android 官方推荐使用 libs.versions.toml 集中管理版本。文件位于 gradle/ 目录下,所有模块通过 libs.* 引用依赖。

// gradle/libs.versions.toml
[versions]
kotlin = "1.9.22"
agp = "8.2.2"
compose-bom = "2024.02.00"
lifecycle = "2.7.0"
navigation = "2.7.7"
hilt = "2.50"
retrofit = "2.9.0"

[libraries]
kotlin-stdlib = { group = "org.jetbrains.kotlin", name = "kotlin-stdlib", version.ref = "kotlin" }
lifecycle-viewmodel-ktx = { group = "androidx.lifecycle", name = "lifecycle-viewmodel-ktx", version.ref = "lifecycle" }
lifecycle-runtime-ktx = { group = "androidx.lifecycle", name = "lifecycle-runtime-ktx", version.ref = "lifecycle" }
hilt-android = { group = "com.google.dagger", name = "hilt-android", version.ref = "hilt" }
hilt-android-compiler = { group = "com.google.dagger", name = "hilt-android-compiler", version.ref = "hilt" }
retrofit = { group = "com.squareup.retrofit2", name = "retrofit", version.ref = "retrofit" }
retrofit-gson = { group = "com.squareup.retrofit2", name = "converter-gson", version.ref = "retrofit" }

[plugins]
android-application = { id = "com.android.application", version.ref = "agp" }
android-library = { id = "com.android.library", version.ref = "agp" }
kotlin-android = { id = "org.jetbrains.kotlin.android", version.ref = "kotlin" }
hilt = { id = "com.google.dagger.hilt.android", version.ref = "hilt" }

在各模块的 build.gradle.kts 中使用方式:

// feature/login/build.gradle.kts
plugins {
    alias(libs.plugins.android.library)
    alias(libs.plugins.kotlin.android)
    alias(libs.plugins.hilt)
}

android {
    namespace = "com.example.feature.login"
    compileSdk = 34
    defaultConfig { minSdk = 24 }
}

dependencies {
    implementation(libs.lifecycle.viewmodel.ktx)
    implementation(libs.hilt.android)
    kapt(libs.hilt.android.compiler)

    implementation(project(":lib:core"))
    implementation(project(":lib:data"))
}
⚠️ 注意:kapt、ksp 等注解处理器版本也要统一纳入 catalog,避免编译时使用不同版本的 annotation processor 导致冲突。

1.5 模块化工程骨架流程图

下图展示了典型的 ViewModel 模块化工程中各模块的依赖关系与数据流向。

Android 模块化工程骨架(ViewModel 视角) app (入口) :feature:login :feature:home :feature:… :lib:core (基类/工具) :lib:data (Repository) :lib:network :lib:test-utils 🟢 绿色 = lib 库模块   🔴 红色 = feature 特征模块   🟣 紫色 = 测试共享库   🔵 蓝色 = 应用入口   虚线 = 测试依赖
💡 依赖方向自顶向下:app → feature → lib。feature 模块不应直接依赖其他 feature 模块,若需共享数据应通过 lib:core 或导航路由实现。

1.6 实现流程(6步搭建)

  1. 创建项目:Android Studio 新建 Empty Activity 项目,删除默认 app 模块以外的多余文件。
  2. 生成目录结构:在根目录下创建 feature/、lib/ 文件夹,并在每个子文件夹内新建 build.gradle.kts 和 src/main/ 目录。
  3. 配置 settings.gradle.kts:注册所有模块路径,详见 1.2 节。
  4. 创建 Version Catalog:在 gradle/ 下新建 libs.versions.toml,定义版本、库、插件。
  5. 编写根 build.gradle.kts:只声明插件解析,具体插件由子模块通过 alias 引入。
  6. 编写各模块 build.gradle.kts:按角色配置 android 插件、namespace、dependencies(使用 libs.* 和 project())。

1.7 调试与常见错误

⚠️ 常见错误 1:模块路径不匹配。例如 settings 中写了 :feature:login,但磁盘上 feature/login 目录下缺少 build.gradle.kts,会报 Project with path ‘:feature:login’ could not be found。
⚠️ 常见错误 2:Version Catalog 版本不一致。如果某个模块直接硬编码了版本号,而 catalog 中升级了该库,会导致运行时类冲突。解决办法:所有模块必须统一使用 libs.*,禁止裸写 implementation("xxx:1.0")。
💡 调试技巧:在 Android Studio 的 Terminal 中执行 ./gradlew projects 和 ./gradlew dependencies --configuration releaseRuntimeClasspath 可以快速查看模块树和依赖树。

1.8 性能与稳定性优化

  • 按需编译:利用 Gradle 的 --parallel 参数、配置 org.gradle.parallel=true 并行构建。
  • 模块化缓存:在 CI 中缓存 .gradle 目录,避免重复下载依赖。
  • 减少 module 间直接引用:feature 模块只应依赖 lib 模块,避免 feature A → feature B 的横向耦合。
  • 使用 BuildConfig 开关:在 buildConfigField 中定义 module 级别的 debug/release 切面,避免 feature 模块运行时加载多余的 ViewModel 初始化代码。
  • 检查依赖树:定期运行 ./gradlew :app:dependencies 确认没有重复或冲突的库版本。
✅ 完成后,你的项目结构应类似:
ViewModelModularApp/
├── app/
├── feature/
│ ├── login/
│ └── home/
├── lib/
│ ├── core/
│ ├── data/
│ ├── network/
│ └── test-utils/
└── gradle/
└── libs.versions.toml