介绍
模块化和组件化
模块化:
将一个程序按照功能做拆分,分成独立的模块,每个模块只包含和它功能相关的内容;
组件化:

- 组件对应单独的功能组件,比如:登录组件,支付组件;
- 每个组件都可以单独编译开发,抽出SDK发布;
- 一个模块包含了一个或多个组件;
优势:
- 减少了编译时间:每个业务功能,可以独立编译运行;
- 减少了沟通成本,一定程度上减少了个人开发风格的差异;
- 解耦:将一个app分成多个模块,一个模块就是一个组件;
- 复用:可以新项目微调/直接使用;
组件分层
- 基础组件:
- 基础公共模块,最底层的;
- 网络请求框架,图片加载框架等主流的第三方库;
- SDK;
- common组件
- 支持业务/功能组件,依赖基础组件;
- 业务组件和功能组件只依赖此组件俩获取基础能力;
- 功能组件
- 依赖基础组件层;
- 对一些公用的功能业务进行封装实现;
- 业务组件
- 依赖基础组件层和一些公用功能组件;
- 各组件不通信,得通过路由通信;
- 业务组件可以在library和application之间切换,但是最后打包时必须是library ;
- 主工程
- 依赖各业务组件;
- 除了全局的配置和主Activity之外,不包含业务代码,是应用的入口;
组件化项目的搭建
抽离共用的build.gradle版本数据
每个模块独立开发,可能会遇到版本信息不一致,这时我们需要统一管理项目的依赖库;
怎么管理:
- 创建config.gradle文件:一些sdk版本,依赖库;
java
ext{
//ext是指额外的属性和变量,整个构建脚本中重复使用和共享;
isDebug = false;
android = [
compileSdkVersion: 33, //编译app的最低SDK版本
minSdkVersion : 32,//运行app的最低SDK版本
targetSdkVersion : 33,//目标pp的的最低SDK版本
versionCode : 1,//指定可以识别该app数字
versionName : "1.0"//编指定可以识别该app的字符
]
//每个模块的application地址
applicationId = {
// "app" : "com.example.dome",
}
//常用库的依赖
library = [
"appcompat" : "androidx.appcompat:appcompat:1.6.1",
"material" : "com.google.android.material:material:1.5.0",
"constraintlayout": "androidx.constraintlayout:constraintlayout:2.1.4"
]
//第三方库
libGson = "com.google.code.gson:gson:2.8.6"
libARouter = "com.alibaba:arouter-api:1.5.2"
libARouterCompiler = "com.alibaba:arouter-compiler:1.5.2"
}
- 让总的build.gradle去apply它;
java
// Top-level build file where you can add configuration options common to all sub-projects/modules.
plugins {
alias(libs.plugins.android.application) apply false
alias(libs.plugins.android.library) apply false
}
apply from:"config.gradle"
- 以后的版本修改改config.gradle;
创建基础层
-
建立一个Module,然后可以放在一个包下统一管理:

-
修改该模块下的Build.gradle,主要要和config.gradle搭配使用;
java
plugins {
alias(libs.plugins.android.library)
}
def swy = rootProject.ext
android {
namespace swy.applicationId.libbase
compileSdk swy.android.compileSdkVersion
defaultConfig {
minSdk swy.android.minSdkVersion
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
}
}
dependencies {
api swy.library.appcompat
api swy.library.material
api swy.library.constraintlayout
//等价于
library.forEach {k,v->implementation v}
api swy.libGson
implementation libs.appcompat
implementation libs.material
testImplementation libs.junit
androidTestImplementation libs.ext.junit
androidTestImplementation libs.espresso.core
}
- 要获得项目根目录的引用,得到ext ,使用公用依赖等;
- 使用了def , 减少了rootProject.ext的次数,提高性能;
- 改动:
- 引入rootProject.ext;
- 改变命名空间:
namespace swy.applicationId.libbase- 使用android的[]下的一些版本;
- 依赖:添加公用依赖和第三方库依赖;
- api的方式引用:a模块导入依赖,b模块通过api 可以导入a导入依赖;
创建组件层
- 创建Module: 需要注意的点有:我们需要在我们组件模块的包名前加上module(或者其他的),否则可能包导致冲突;这次我们需要点第一个;使用application插件;
- 创建debug模块,移动AM到debug模块中;

打包模式下不需要其他的活动清单,对里面内容改动:
java
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android">
<application
>
<activity
android:name=".MainActivity"
android:exported="true">
</activity>
</application>
</manifest>
这样做是因为,如果是单独调试,那么需要一个启动页AM, 但是如果是打包的话,合并就会有多个启动页,这个时候就不需要其他的活动清单;
- 关于build.gradle的变动:
java
if(rootProject.ext.isDebug){
apply plugin: 'com.android.application'
}
else{
apply plugin: 'com.android.library'
}
def swy = rootProject.ext
android {
namespace swy.applicationId.login
compileSdk swy.android.compileSdkVersion
defaultConfig {
if(swy.isDebug){
applicationId swy.applicationId.login
}
minSdk swy.android.minSdkVersion
targetSdk swy.android.targetSdkVersion
versionCode swy.android.versionCode
versionName swy.android.versionName
testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
}
buildTypes {
release {
minifyEnabled false
proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro'
}
}
compileOptions {
sourceCompatibility JavaVersion.VERSION_11
targetCompatibility JavaVersion.VERSION_11
}
sourceSets{
main{
if(swy.isDebug){
manifest.srcFile 'src/main/debug/AndroidManifest.xml'
}
else{
manifest.srcFile 'src/main/AndroidManifest.xml'
java{
exclude "**/debug/**"
}
}
}
}
}
dependencies {
implementation project(':modulesBase:libBase')
implementation libs.appcompat
implementation libs.material
implementation libs.activity
implementation libs.constraintlayout
testImplementation libs.junit
androidTestImplementation libs.ext.junit
androidTestImplementation libs.espresso.core
}
关于变动想说明以下几点:
- 为了达到调试时可以作为单独运行,打包时就会变成一个arr文件配合app使用,这时:
java
if(rootProject.ext.isDebug){
apply plugin: 'com.android.application'
}
else{
apply plugin: 'com.android.library'
}
- 判断是不是出于调试模式,如果是的话, 'com.android.application'
如果不是apply plugin: 'com.android.library' - applicationId : app运行需要这个标识符来启动login的运行,所以如果是调试模式,我们需要定义;
- sourceSets:用于指定安卓项目的源集,用于构建app所需要的项目源代码或者资源等的配置;
- Main: sourceSets内的源集;
- 条件语句:根据不同模式来决定使用哪一个清单文件;
- "/debug/" : **表示匹配任意数量的目录,总的表示移除任何存在debug的路径
- 引入基础模块: implementation project(':modulesBase:libBase')
搭建App层
java
app的build.gradle:
plugins {
alias(libs.plugins.android.application)
}
def swy = rootProject.ext
android {
namespace swy.applicationId.app
compileSdk swy.android.compileSdkVersion
defaultConfig {
if(swy.isDebug){
applicationId swy.applicationId.login
}
minSdk swy.android.minSdkVersion
targetSdk swy.android.targetSdkVersion
versionCode swy.android.versionCode
versionName swy.android.versionName
testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
buildConfigField("boolean","isDebug",String.valueOf(isDebug))
}
buildFeatures{
buildConfig true
}
buildTypes {
release {
minifyEnabled false
proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro'
}
}
compileOptions {
sourceCompatibility JavaVersion.VERSION_11
targetCompatibility JavaVersion.VERSION_11
}
}
dependencies {
implementation project(':modulesBase:libBase')
if(!swy.isDebug){
implementation project(":modulesCore:login")
}
testImplementation libs.junit
androidTestImplementation libs.ext.junit
androidTestImplementation libs.espresso.core
}
buildConfigField("boolean","isDebug",String.valueOf(isDebug))
它可以把gradle数据映射到Java类里面,可以在Java类中使用gradle数据;
java
if(!swy.isDebug){
implementation project(":modulesCore:login")
}
- 启动 buildConfigField功能
java
buildFeatures{
buildConfig true
}
搭建成果
如果Debug是tue:

如果Debug是false:

改:把所有的swy.isDebug改成isDebug.toBoolean()
在gradle.properties中的;
isDebug = false 修改isDebug值;