Android 搭建模块化项目流程及建议
搭建模块化项目会遇到的几个问题
- 独立模块和组合
- 第三方库依赖管理
- 模块间的跳转
- 模块之间的共性配置
- 资源文件命名规范
- Debug 和 Release 源代码配置
- 模块初始化管理
项目环境:
yaml
Android Studio Meerkat Feature Drop | 2024.3.2
Build #AI-243.25659.59.2432.13423653, built on April 30, 2025
Runtime version: 21.0.6+-13368085-b895.109 amd64
独立模块和组合
- 在全局配置文件中定义 isRelease
通常可以在项目的 gradle.properties
或一个独立的 gradle
配置文件中定义变量,例如
ini
# gradle.properties
isRelease=true
或者通过 ext 在项目级 build.gradle 中定义:
ini
// Project-level build.gradle
ext {
isRelease = true
}
如果是放在新建的 .gradle
文件中,需要在根 build.gradle 文件中引用,其他地方才能正常引用
scss
plugins {
alias(libs.plugins.android.application) apply false
alias(libs.plugins.kotlin.android) apply false
alias(libs.plugins.android.library) apply false
alias(libs.plugins.hilt.android) apply false
}
// 添加引用
apply from: 'env.gradle'
- 动态切换 Module 类型
修改当前模块的 build.gradle 文件,根据 isRelease 的值决定使用 com.android.application 插件还是 com.android.library 插件
scss
// 修改前
plugins {
alias(libs.plugins.kotlin.android)
alias(libs.plugins.android.library)
}
// 修改后
plugins {
alias(libs.plugins.kotlin.android)
}
// apply plugin 或者 apply { plugin } 方式都可以
if (isRelease){
apply plugin: 'com.android.application'
}else{
apply { plugin 'com.android.library'}
}
改完是否为 library 还是 application 后,再改 android#defaultConfig
中是否含有 applicationId 属性
arduino
if (!isRelease){
applicationId "com.zqautomotive.service"
targetSdk 35
versionCode 1
versionName "1.0"
}
minSdk 24
最后在主 APP 中修改
scss
if (isRelease) {
// 当 service 为 library 时才引入
implementation project(':service')
}
第三方库依赖管理
Android 目前是以 libs.versions.toml
文件来管理依赖库
模块间跳转
可以采用阿里的路由框架 ARouter 或反射获取到 Class 后, startActivity 进行跳转
模块间共性配置
在多模块间很多配置都是相同的,可以提取到一个 gradle 文件中
arduino
plugins {
alias(libs.plugins.android.library)
alias(libs.plugins.kotlin.android)
}
android {
namespace 'com.zqautomotive.usb'
compileSdk 35
defaultConfig {
minSdk 24
testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
consumerProguardFiles "consumer-rules.pro"
}
buildTypes {
release {
minifyEnabled false
proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro'
}
}
compileOptions {
sourceCompatibility JavaVersion.VERSION_11
targetCompatibility JavaVersion.VERSION_11
}
kotlinOptions {
jvmTarget = '11'
}
}
dependencies {
implementation libs.androidx.core.ktx
implementation libs.androidx.appcompat
implementation libs.material
testImplementation libs.junit
androidTestImplementation libs.androidx.junit
androidTestImplementation libs.androidx.espresso.core
}
比如上面的配置,除了 namespace
不同其他的都是相同配置,提取到 app.gradle 中,但不能有 plugins
标签,该标签只出现在项目级 build.gradle 中,其他的不变。
在模块间引用
csharp
plugins {
alias(libs.plugins.android.library)
alias(libs.plugins.kotlin.android)
}
// 添加共性配置
apply from: '../app.gradle'
android {
// 保留 namespace
namespace 'com.zqautomotive.usb'
}
dependencies {
// 如果有单独需要的依赖,添加即可
}
资源文件命名规范
在不同的 model 中,使用命名前缀
arduino
android {
// 资源前缀
resourcePrefix 'usb_'
}
Debug 和 Release 源代码配置
在 android {} 下配置过滤
arduino
sourceSets {
main {
if (isRelease){
// 任意路径下包含 debug 目录下的文件都会过滤掉
java.exclude '**/debug/**'
}
}
}
多模块初始化管理
在 base 中提供一个中间接口
kotlin
class ModuleMediator {
interface AppInitial {
fun init(app: Application)
}
fun init(app: Application) {
val appclasses = arrayOf(
"com.zqautomotive.service.App",
"com.zqautomotive.usb.App",
"com.zqautomotive.bluetooth.App",
)
for (className in appclasses) {
try {
val clazz = Class.forName(className)
val instance = clazz.newInstance() as AppInitial
instance.init(app)
} catch (e: Exception) {
e.printStackTrace()
}
}
}
}
其他模块 APP 实现 ModuleMediator.AppInitial
接口即可