前言
組件化項目的意義主要體現在這幾個方面,首先就是面試的時候,如果簡歷上寫了三五年的工作經歷,但是被問到組件化的相關原理打不上來,確實說不過去。在開發需求層面,即不相互依賴、又可以相互交互、任意組合、高度解耦;在團隊開發效率層面,可以分模塊打包、測試,統一版本管理。
Phone Module和Android Library區別、切換
新建common公共庫、order訂單庫、personal個人信息庫
這裏爲了便於演示,新建Phone Module 的order和Android Library的personal,在組件化部署中如何進行切換
有了上一篇文章的分析,我們知道可以將各個子模塊build.gradle文件中的公共屬性抽取出來到單獨的gradle文件config.gradle文件,在項目根目錄下的build.gradle頭部加入自定義config.gradle,apply from: “config.gradle”,相當於layout佈局中加入include語法
// 添加多個自定義屬性,可以通過ext代碼塊
ext{
/**
* 定義一個項目全局變量isRelease,用於動態切換:組件化模式 / 集成化模式
* false: 組件化模式(子模塊可以獨立運行),
* true :集成化模式(打包整個項目apk,子模塊不可獨立運行)
*/
isRelease = false
// 建立Map存儲,對象名、key都可以自定義,groovy糖果語法,非常靈活
androidId = [
compileSdkVersion: 29,
buildToolsVersion: "29.0.3",
minSdkVersion : 21,
targetSdkVersion : 29,
versionCode : 1,
versionName : "1.0",
testInstrumentationRunner: "androidx.test.runner.AndroidJUnitRunner",
consumerProguardFiles: "consumer-rules.pro"
]
appId = [
app: "xpf.moudlar.deploy",
order: "xpf.moudlar.deploy.order",
personal: "xpf.moudlar.deploy.personal"
]
//生產開發環境URL
url = [
"debug_entrance": "https://11.22.33.44/debug",
"release_entrance": "https://11.22.33.44./release"
]
//依賴相關
dependencies_impl = [
appcompat: 'androidx.appcompat:appcompat:1.1.0',
constraintlayout:'androidx.constraintlayout:constraintlayout:1.1.3',
junit: 'junit:junit:4.12',
test: 'androidx.test.ext:junit:1.1.1',
espresso: 'androidx.test.espresso:espresso-core:3.2.0',
recyclerView: 'androidx.recyclerview:recyclerview:1.1.0'
]
}
在order和personal模塊的build.gradle文件中做如下處理,就可以根據isRelease的值,將order和personal在進行動態切換
if (isRelease) {//集成化環境,正式打包環境
apply plugin: 'com.android.library'// 配置爲library
} else {// 組件化環境,測試環境,可以單獨運行
apply plugin: 'com.android.application' // 配置爲phone module
}
android {
compileSdkVersion androidId.compileSdkVersion
buildToolsVersion androidId.buildToolsVersion
defaultConfig {
if (!isRelease) {// 如果是集成化環境,不能有applicationId
applicationId appId.personal//組件化模式能獨立運行纔能有applicationId
}
minSdkVersion androidId.minSdkVersion
targetSdkVersion androidId.targetSdkVersion
versionCode androidId.versionCode
versionName androidId.versionName
testInstrumentationRunner androidId.testInstrumentationRunner
if (isRelease) {
// 筆者在升級3.6之後,新建android library 發現有有如下屬性
consumerProguardFiles androidId.consumerProguardFiles
}
// 這個方法接收三個非空的參數
// 第一個參數:確定值的類型
// 第二個參數:指定key的名字
// 第三個參數:傳值(必須是String)
// 爲什麼需要定義這個?因爲在src代碼中有可能需要跨模塊交互,如果是組件化模塊(開發環境)相當於兩個App交互,顯然不行
// 切記:不能在android節點下,只能在defaultConfig或buildTypes節點下
// rebuild之後,BuildConfig文件中有boolean isRelease 屬性了,可以通過它判斷環境,進行相關操作
buildConfigField("boolean", "isRelease", String.valueOf(isRelease))
}
buildTypes {
// 在配置app和librayt切換時,主要前面的部分,通過isRelease進行判斷配置,受篇幅所限,其餘部分省略
...
}
}
dependencies {
...
}
Gradle搭建組件化項目環境
經過前面的步驟,當isRelease爲false時,各個子模塊均可獨立運行,但是之前創建personal的時候是library,雖然經過配置理論上變成了可獨立運行的app。但是由於沒有AndroidManifest和res目錄下的drawable和layout等資源,運行會報錯。所以還需要將order模塊的AndroidManifest和res目錄下的所以資源拷貝到personal對應目錄,然後更改爲符合personal的條件。
組件化開發規範:
- order order_前綴(src類和res資源)
- personal personal_前綴(src類和res資源)
- app 可不改,讓它默認
此時當isRelease置爲false時,order和personal均可獨立正常運行了,這一部分較爲簡單,代碼就不貼了。
集成化模式開發、組件化模式開發
前面提到過,組件化模式就是isRelease置爲false,各個子模塊可獨立運行,一次打包爲多個apk文件,可以選擇性的進行調試。集成化模式就是isRelease置爲true,各個子模塊不能獨立運行,整個項目打包爲一個apk文件,子模塊此時爲library。
組件化開發的臨時代碼,集成化打包時動態隔離
試想一下,在組件化模式下,需要進行多種業務的調試,可能會創建多個文件,但是在集成化模式下,我們並不希望這些文件打包到apk文件中。此時在order和personal的build.gradle文件中進行如下配置解決這個問題, 這裏只貼出與本問題相關部分的配置
if (isRelease) {
apply plugin: 'com.android.library'
} else {
apply plugin: 'com.android.application'
}
android {
...
defaultConfig{
...
}
buildTypes {
...
}
// 配置資源路徑,方便測試環境,打包不集成到正式環境
sourceSets{
main {
if (!isRelease) {
// 註釋1
// 如果是組件化模式,需要單獨運行時
manifest.srcFile 'src/main/debug/AndroidManifest.xml'
} else {
// 註釋2
// 集成化模式,整個項目打包apk
manifest.srcFile 'src/main/AndroidManifest.xml'
java {
// 註釋3
// 集成化時debug目錄下文件不需要合併到工程
exclute '**/debug/**'
}
}
}
}
}
dependencies {
...
}
正如註釋處所示,在組件化模式和集成化模式下,指定不同目錄下的AndroidManifest文件,註釋3處,表示集成化模式時,子模塊所有debug目錄下的文件不需要合併到工程,也就不會打包到apk文件中。在需要參照配置創建對應的debug目錄和AndroidManifest文件,在debug目錄下的AndroidManifest中註冊,對應debug目錄下的Personal_DebugMainActivity等文件。當isRelease爲false時,就會顯示Personal_DebugMainActivity對應的內容,但是isRelase爲true時,Personal_DebugMainActivity文件又不會打包到apk文件當中。