組件化項目的意義
組件化,簡單來說,就是將一個APP的業務功能進行拆分,每一個功能都是一個單獨的工程,每個工程都能獨立運行,且只包含自己的業務,最後整個APP由多個拆分出的組件集成而成
組件化開發的優點有以下幾點:
- 極大提高工程編譯速度
進行組件化拆分後,每個業務或者功能都是一個單獨的工程,這個單獨的工程可以獨立編譯運行,編譯運行速度快,減少時間成本; - 業務模塊解耦,利於多人團隊協作開發,提高團隊開發效率
業務組件之間不能相互引用,每個組件都把對應的業務功能放在一個工程裏去實現,彼此互不打擾。 在團隊開發中,每個人只負責自己的業務模塊,便於開發測試; - 提高功能重用性
不同的組件實現的業務功能不同,可以像搭積木一樣任意排列形成新的APP
組件化架構設計圖
phone module 和 Android Library 的區別
phone module: 新建出可以獨立運行的模塊,與創建項目時自動創建的app module 是一樣的,在build.gradle中 是 apply plugin: ‘com.android.application’ ,android 配置下包含applicationId;
Android Library: 新建出的Android庫,不能直接運行,可被其他module引用,在build.gradle 中,是library “apply plugin: ‘com.android.library’”,Android配置下不包含applicationId.
Gradle搭建組件化項目環境
爲了使多個模塊之間配置一致,則可以通過引入統一配置文件進行配置,配置過程如下:
- 在工程中創建config.gradle文件
- 在文件中設置統一配置內容
// 必須在ext標籤下進行配置
ext {
// 標記是測試版本還是正式發佈版本,在模塊中可以根據這個值進行不同的配置
isRelease = true
//相關編譯環境的版本配置
androidId = [
compileSdkVersion: 28,
buildToolsVersion :"29.0.0",
minSdkVersion : 21,
targetSdkVersion : 28,
versionCode: 1,
versionName :"1.0"
]
//不同模塊的applicationId
appId = [
app : "com.example.zhangzd.zujiandemo",
order: "com.example.zhangzd.order",
personal: "com.example.zhangzd.personal"
]
//support包的版本
supportLibrary = "28.0.0"
//第三方依賴配置
dependencies = [
// ${supportLibrary}表示引用一個變量
"appcompat" : "com.android.support:appcompat-v7:${supportLibrary}",
"recyclerview": "com.android.support:recyclerview-v7:${supportLibrary}",
"constraint" : "com.android.support.constraint:constraint-layout:1.1.3",
"okhttp3" : "com.squareup.okhttp3:okhttp:3.10.0",
"retrofit" : "com.squareup.retrofit2:retrofit:2.5.0",
"fastjson" : "com.alibaba:fastjson:1.2.58",
]
}
- 在工程的build.gradle 中,通過 apply from : “config.gradle” 引入配置文件;
- 在模塊的build.gradle中應用配置文件,以APP模塊爲例,配置文件如下
apply plugin: 'com.android.application'
//定義變量androidId等,引入配置文件中的配置信息,
def androidId = rootProject.ext.androidId
def appId = rootProject.ext.androidId
def support = rootProject.ext.dependencies
android {
// 通過創建的變量配置具體的信息
compileSdkVersion androidId.compileSdkVersion
buildToolsVersion androidId.buildToolsVersion
defaultConfig {
applicationId appId.app
minSdkVersion androidId.minSdkVersion
targetSdkVersion androidId.targetSdkVersion
versionCode androidId.versionCode
versionName androidId.versionName
// 這個方法接收三個非空的參數,第一個:確定值的類型,第二個:指定key的名字,第三個:傳值(必須是String)
// 爲什麼需要定義這個?因爲src代碼中有可能需要用到跨模塊交互,如果是組件化模塊顯然不行
// 切記:不能在android根節點,只能在defaultConfig或buildTypes節點下
buildConfigField("boolean", "isRelease", String.valueOf(isRelease))
multiDexEnabled false
}
buildTypes {
release {
minifyEnabled false
proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro'
}
}
}
dependencies {
implementation fileTree(dir: 'libs', include: ['*.jar'])
// 循環添加第三方依賴,最簡單的方式,可以不循環一個一個添加
support.each{ k, v ->
implementation v
}
if (isRelease) {
implementation project(":order")
implementation project(":personal")
}
}
集成化模式開發、組件化模式開發
集成化模式開發:即模塊是APP的組成部分,所有的模塊組裝起來便是一個完整的APP,在項目中的表現形式是,在一個工程中,只有一個phone module ,其他的只能作爲Android 的library被引用,只能運行phone module ,其他模塊不能直接運行。例如在一個APP中,首先由主模塊(phone module)app模塊,其次是Oder和Personal兩個library,具體如下圖
組件化模式開發:即每個模塊都是一個phone module ,可以單獨運行,單獨調試。例如,除了app模塊外,Order和Personal 都是phone module,可以單獨運行,如圖
在團隊開發過程中,每個成員可能只開發一個功能模塊,不同的人開發不同功能模塊,此時需要組件化開發模式,每個模塊都是一個單獨的phone module,可以進行單獨運行和測試,加快開發速度。當打包上線時,需要將所有的功能模塊與主模塊一同打包成一個APP,此時需要組件化開發模式,因此需要兩種模式的靈活轉換,我們也可以通過gradle 的配置實現靈活轉換。要進行切換,就需要知道phone module 和Android library的區別,即上邊介紹的兩個區別。因此兩種模式的切換,即非主模塊phone module 和Android library的切換。步驟如下:
- config.gradle 配置文件中添加 isRelease = false ,該變量標識是否是測試環境還是正式打包環境;
- 在非主模塊中進行如下配置,以order爲例:
//通過定義的isRelease 變量,判斷此時是否是測試環境嗎,測試環境需要切換爲組件化開發模式,即每個模塊都是可以單獨運行的
if (isRelease) {
// 是release時 ,將module設置爲library
apply plugin: 'com.android.library'
}else {
// 不是是release時 ,將module設置爲application
apply plugin: 'com.android.application'
}
def androidId = rootProject.ext.androidId
def appId = rootProject.ext.androidId
def support = rootProject.ext.dependencies
android {
compileSdkVersion androidId.compileSdkVersion
buildToolsVersion androidId.buildToolsVersion
defaultConfig {
//發佈版本時沒有applicationID
if (!isRelease) {
applicationId appId.order
}
minSdkVersion androidId.minSdkVersion
targetSdkVersion androidId.targetSdkVersion
versionCode androidId.versionCode
versionName androidId.versionName
}
buildTypes {
release {
minifyEnabled false
proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro'
}
}
}
dependencies {
implementation fileTree(dir: 'libs', include: ['*.jar'])
support.each{k,v ->
implementation v
}
}
- 在主模塊中,配置當非release模式下,不引用order等模塊,當release模式時,引用
dependencies {
implementation fileTree(dir: 'libs', include: ['*.jar'])
support.each{k,v ->
implementation v
}
// release 時才進行依賴
if (isRelease) {
implementation project(":order")
implementation project(":personal")
}
}
經過以上的配置,我們只需要在config.gradle 中更改isRelease變量,即可進行兩種模式的自由切換。
組件化開發時的臨時代碼,集成化打包時動態隔離
當我們切換到集成開發模式並打包成一個Apk時,會發現一個問題,那就是在非主模塊,我們的一些測試文件,比方說mainActivity等,只是在測試時纔會用到,打包時不需要打包到apk,這個需要怎麼解決呢?
我們可以通過配置sourceSet設置資源路徑來解決這個問題
- 在非主模塊的main路徑下,新建debug路徑,該路徑下創建測試環境時的AndroidManifest.xml文件;
- 在Java.xxx.xxx.xxx.下創建debug,該路徑下存放測試的Java代碼
- 在該模塊的build.gradle中配置sourceSet
if (isRelease) {
apply plugin: 'com.android.library'
} else {
apply plugin: 'com.android.application'
}
def androidId = rootProject.ext.androidId
def appId = rootProject.ext.androidId
def support = rootProject.ext.dependencies
android {
compileSdkVersion androidId.compileSdkVersion
buildToolsVersion androidId.buildToolsVersion
defaultConfig {
//發佈版本時沒有applicationID
if (!isRelease) {
applicationId appId.order
}
minSdkVersion androidId.minSdkVersion
targetSdkVersion androidId.targetSdkVersion
versionCode androidId.versionCode
versionName androidId.versionName
}
buildTypes {
release {
minifyEnabled false
proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro'
}
}
// 配置資源路徑,方便測試環境中的內容不會被打包到apk中去
sourceSets {
main{
if (isRelease) {
//集成化模式,整個項目打包成一個apk
manifest.srcFile 'src/main/AndroidManifest.xml'
java {
// debug 目錄下的文件不需要打包到apk中去
exclude '**/debug/**'
}
}else {
//組件化模式,需要單獨運行
manifest.srcFile 'src/main/debug/AndroidManifest.xml'
}
}
}
}
dependencies {
implementation fileTree(dir: 'libs', include: ['*.jar'])
implementation 'androidx.appcompat:appcompat:1.0.2'
implementation 'androidx.constraintlayout:constraintlayout:1.1.3'
support.each { k, v ->
implementation v
}
}
- 重新編譯打包,就可以了
最後查看apk ,打出的apk中不包含測試用的A,B等類