Android 搭建模块化项目流程及建议

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

独立模块和组合

  1. 在全局配置文件中定义 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'
  1. 动态切换 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 接口即可

相关推荐
自由鬼6 小时前
企业架构框架深入解析:TOGAF、Zachman Framework、FEAF与Gartner EA Framework
程序人生·架构
jiedaodezhuti7 小时前
EFK架构的数据安全性
架构
喜欢踢足球的老罗7 小时前
自动化模型管理:MediaPipe Android SDK 中的模型文件下载与加载机制
android·运维·自动化
蓝色天空的银码星7 小时前
SpringCloud微服务架构下的日志可观测解决方案(EFK搭建)
spring cloud·微服务·架构
汪子熙9 小时前
在 Word 里编写 Visual Basic 调用 DeepSeek API
后端·算法·架构
AgilityBaby10 小时前
Untiy打包安卓踩坑
android·笔记·学习·unity·游戏引擎
灏瀚星空10 小时前
高频交易技术:订单簿分析与低延迟架构——从Level 2数据挖掘到FPGA硬件加速的全链路解决方案
人工智能·python·算法·信息可视化·fpga开发·架构·数据挖掘
硬件学长森哥11 小时前
Android音视频多媒体开源框架基础大全
android·图像处理·音视频
二流小码农11 小时前
鸿蒙开发:CodeGenie万能卡片生成
android·ios·harmonyos
holdonononnn11 小时前
什么是 Monorepo ? 如何实现?
架构·前端框架