前言
之前學(xué)習(xí)組件化-路由的時(shí)候也是花費(fèi)了不少的時(shí)間,其實(shí)學(xué)習(xí)技術(shù)都是這樣,自己弄懂了大部分東西之后就會(huì)覺得這個(gè)知識(shí)好像并不是那么難。
這里的 “ 組件化-路由技術(shù) ” 分成兩篇文章講解,確實(shí)內(nèi)容略多一點(diǎn),第一篇主要就是講解組件化,而第二篇就主要講解路由知識(shí),這里是第二篇文章的鏈接。
我盡力講得更加仔細(xì)一點(diǎn),希望剛接觸這項(xiàng)技術(shù)的小伙伴能夠看得懂。
組件化的作用
組件化技術(shù)主要是進(jìn)行項(xiàng)目比較大的團(tuán)隊(duì)才會(huì)采用的,想必它的作用很多小伙伴是清楚的了,我就簡(jiǎn)單提幾點(diǎn)就行了。
- 提高編譯速度: 該技術(shù)可以實(shí)現(xiàn)單獨(dú)一個(gè)組件作為一個(gè)Application進(jìn)行編譯運(yùn)行,例如我只想測(cè)試一下“登錄、注冊(cè)”組件,而我不必編譯、運(yùn)行整個(gè)項(xiàng)目,這樣就可以提高我的開發(fā)效率。
- 解耦程度大: 解耦程度大不多解釋,因?yàn)楫吘挂粋€(gè)組件都可以單獨(dú)運(yùn)行了,你想它的解耦程度大不大呢?特別是將common(公共層)抽出來(lái)之后,用起來(lái)是真的舒服~
- 利于團(tuán)隊(duì)開發(fā):這一點(diǎn)上感觸頗深,在任務(wù)分配完成之后,就是感覺跟其它人的代碼就完全分割開來(lái)了,寫代碼的過(guò)程很舒服,而且在git管理代碼的過(guò)程中失誤率也會(huì)小很多。
組件化實(shí)現(xiàn)
組件化實(shí)現(xiàn)比較輕松,下面我會(huì)將完整步驟都描述出來(lái)。
1. 統(tǒng)一每個(gè)組件的配置文件
第一步就是新建幾個(gè)組件,選中項(xiàng)目new module就可以了,結(jié)果如下圖所示:

在這里,我的想法是app作為應(yīng)用殼組件,它負(fù)責(zé)APK的打包,管理其它組件,而沒(méi)有業(yè)務(wù)邏輯;lib_common是公共層組件,是放置共用的網(wǎng)絡(luò)請(qǐng)求、工具類的地方;而lib_home、lib_chat組件就是我們的業(yè)務(wù)邏輯組件。
如上圖所示,每一個(gè)組件都有自己的build.gradle文件,我們肯定需要配置文件(.gradle)里信息的統(tǒng)一,防止私自修改gradle文件而影響整個(gè)項(xiàng)目的編譯運(yùn)行。我們需要?jiǎng)?chuàng)建一個(gè)config.gradle(上圖所示)來(lái)統(tǒng)一gradle文件,config.gadle文件包含以下信息:

這一個(gè)config.gradle文件需要導(dǎo)入到項(xiàng)目配置文件中去,我們需要在project的build.gradle文件下代碼的頂部加上apply from: "config.gradle"來(lái)將我們的配置文件導(dǎo)入項(xiàng)目。接下來(lái)只需要在每個(gè)組件的build.gradle文件中這么使用:

2. 設(shè)置組件單獨(dú)運(yùn)行時(shí)的AndroidManifests.xml文件
在講之前,我們先做一件事,由于common組件作為共用層,它肯定不需要單獨(dú)運(yùn)行,所以我們先將它導(dǎo)入其它的組件,按照添加三方庫(kù)的辦法,在其它組件的build.gradle文件中添加代碼implementation project(':lib_common'),以此導(dǎo)入本地庫(kù),然后,將app組件下的res文件全部導(dǎo)入common組件中去(layout目錄就不用了,它就是app組件私有的),由于已經(jīng)依賴了common組件,那么app中res的所有文件就可以刪除了,不然就多了,而且重名。
我們可以打開某一個(gè)組件下的AndroidManifests.xml看一下,它沒(méi)有<application></application>標(biāo)簽,因?yàn)樗藭r(shí)是作為一個(gè)庫(kù)來(lái)使用的,它不能夠使用應(yīng)用標(biāo)簽。同理,它也不能配置該標(biāo)簽下的信息,例如應(yīng)用名、主題之類的。按照三方庫(kù)形式導(dǎo)入其它組件后,這個(gè)manifests文件上的信息會(huì)被合并到另外一個(gè)組件的manifests文件上去。
為了使得我們的組件可以單獨(dú)運(yùn)行,我們需要單獨(dú)為它創(chuàng)建一個(gè)manifests文件,我們?cè)赑roject方式查看項(xiàng)目的方式下,在該組件下建立一個(gè)包,就叫alone包吧~,然后在該包下創(chuàng)建AndroidManifests.xml文件,我的建議是直接將app組件下的AndroidManifests.xml文件直接拷貝過(guò)來(lái),然后稍微修改下,像下面這樣:

這里大概能夠理解為什么需要將res文件全部移動(dòng)到common組件中去了吧,不然的app組件和chat組件是沒(méi)有相互依賴的,chat組件就不能夠使用圖片、文字等資源了。
3. 實(shí)現(xiàn)兩種運(yùn)行模式
我們需要使項(xiàng)目有兩種模式,一種是集成模式,一種是單獨(dú)運(yùn)行模式。
首先,我們?cè)趐roject下的gradle.properties文件中添加代碼isRunAlone=true,這個(gè)文件中可以放置項(xiàng)目需要使用的常量值,這句代碼的意思就是定義了一個(gè)Boolean類型變量為true,就是“可單獨(dú)運(yùn)行”吧。
接下來(lái)在其它組件的build.gradle文件下,將頂部apply plugin: 'com.android.library'代碼修改為
if(isRunAlone.toBoolean()) {
apply plugin: 'com.android.application'
}else{
apply plugin: 'com.android.library'
}
這段代碼的意思就是,通過(guò)常量值判斷以哪種形式運(yùn)行代碼,.library就是作為第三方庫(kù)使用,不可單獨(dú)運(yùn)行,.application就是可以作為一個(gè)應(yīng)用單獨(dú)運(yùn)行。
我們要求在單獨(dú)運(yùn)行的模式下,能夠使用我們自定義的manifests文件。以此需要在buildTypes內(nèi)添加以下代碼:
sourceSets {
main {
if (isRunAlone.toBoolean()) {
manifest.srcFile 'src/main/alone/AndroidManifest.xml'
} else {
manifest.srcFile 'src/main/AndroidManifest.xml'
java {
//清除alone目錄下的文件
exclude 'run_alone/**'
}
}
}
}
最后貼出home組件的完整build.gradle文件代碼:
if (isRunAlone.toBoolean()) {
apply plugin: 'com.android.application'
} else {
apply plugin: 'com.android.library'
}
android {
compileSdkVersion rootProject.ext.android.compileSdkVersion
defaultConfig {
minSdkVersion rootProject.ext.android.minSdkVersion
targetSdkVersion rootProject.ext.android.targetSdkVersion
versionCode rootProject.ext.android.versionCode
versionName rootProject.ext.android.versionName
testInstrumentationRunner rootProject.ext.android.testInstrumentationRunner
}
buildTypes {
release {
minifyEnabled false
proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro'
}
sourceSets {
main {
if (isRunAlone.toBoolean()) {
manifest.srcFile 'src/main/alone/AndroidManifest.xml'
} else {
manifest.srcFile 'src/main/AndroidManifest.xml'
java {
//清除run_alone目錄下的文件
exclude 'run_alone/**'
}
}
}
}
}
}
dependencies {
implementation fileTree(dir: 'libs', include: ['*.jar'])
implementation rootProject.ext.dependencies.appcompat
implementation rootProject.ext.dependencies.constraint_layout
implementation 'com.android.support.constraint:constraint-layout:1.1.3'
testImplementation rootProject.ext.dependencies.junit
androidTestImplementation rootProject.ext.dependencies.runner
androidTestImplementation rootProject.ext.dependencies.espresso_core
//導(dǎo)入共用層組件
implementation project(':lib_common')
}
我們可以單獨(dú)運(yùn)行了嗎?不可以,因?yàn)槲覀冞€沒(méi)有啟動(dòng)活動(dòng)
我們?cè)诿恳粋€(gè)組建下創(chuàng)建一個(gè)活動(dòng),并在alone目錄下的manifests文件中將它設(shè)置為啟動(dòng)活動(dòng)。接下來(lái)就可以單獨(dú)運(yùn)行了。
注意事項(xiàng)
1. 資源名沖突
當(dāng)我們切換成集成運(yùn)行模式下的時(shí)候,兩個(gè)組件中資源命名相同的話,就會(huì)導(dǎo)致資源名沖突,系統(tǒng)怎么會(huì)知道你想采用哪一個(gè)xml文件呢?
解決這個(gè)沖突也很簡(jiǎn)單,每一個(gè)組件都加上一個(gè)前綴就行了。添加代碼resourcePrefix "前綴_"在該組件的build.gradle文件中的buildTypes內(nèi)就行了,在你創(chuàng)建xml文件的時(shí)候,系統(tǒng)就會(huì)強(qiáng)制要求你給該xml文件添加前綴,否則就會(huì)編譯報(bào)錯(cuò)。記住,不是編譯器自動(dòng)添加前綴,而是手動(dòng)添加前綴,不添加則編譯報(bào)錯(cuò)。
2. 導(dǎo)庫(kù)問(wèn)題
通過(guò)implementation 形式導(dǎo)入的庫(kù)具有相互依賴性,舉個(gè)栗子,我們?cè)赼pp組件下導(dǎo)入home、chat的組件后,在chat組件中就可以使用home組件的文件,同理在home組件中就可以使用chat組件的文件。
但是,這個(gè)方法在導(dǎo)入第三方庫(kù)的時(shí)候就行不通了。 在某個(gè)組件中使用implementation導(dǎo)入第三方庫(kù),那么就只有該組件能夠使用該第三方庫(kù)。那么我們就應(yīng)該使用api的方式來(lái)實(shí)現(xiàn)第三方庫(kù)導(dǎo)入,例如在common層gradle中加上代碼api 'com.github.bumptech.glide:glide:3.7.0'導(dǎo)入Glide庫(kù),可以實(shí)現(xiàn)在其它組件中也調(diào)用Glide第三方庫(kù)。
僅僅在app組件下導(dǎo)入一次即可,單獨(dú)將其導(dǎo)入其它業(yè)務(wù)組件代碼貼出來(lái):
if (!isRunAlone.toBoolean()) {
api project(":lib_chat")
api project(":lib_home")
}
3. manifests注冊(cè)、權(quán)限問(wèn)題
除了app、common組件,其它業(yè)務(wù)邏輯組件我們都應(yīng)該具有兩張表。但是每一次我們生成一個(gè)活動(dòng)的時(shí)候,編譯器只會(huì)在一張表上面去注冊(cè)活動(dòng),因此一定要記住,我們需要手動(dòng)在另外一張表上面注冊(cè)活動(dòng)。還有就是權(quán)限問(wèn)題,一般我們只需要在common層的manifests文件中將所有權(quán)限都申明就可以了,不然的話,你還需要在業(yè)務(wù)組件上去申明兩次權(quán)限(兩張表)。
4. 簽名配置
由于需要第三方平臺(tái)的使用,需要我們提供應(yīng)用的簽名,我們要統(tǒng)一我們APK的簽名。這里說(shuō)一種最常用的自動(dòng)簽名的方式。在我們手動(dòng)打包一次APK之后,生成了.key文件,接下來(lái)直接代碼啦:
//在build.gradle的android 內(nèi)
signingConfigs {
//簽名配置要在buildtypes之前
//簽名文件放在build.gradle同級(jí)目錄
config {
//填寫自己的key文件的相對(duì)路徑
storeFile file("./key.jks")
storePassword "123456"
keyAlias "123456"
keyPassword "123456"
}
}
buildTypes {
release {
//使用簽名
signingConfig signingConfigs.config
//混淆
minifyEnabled true
proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
}
debug {
signingConfig signingConfigs.config
minifyEnabled true
proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
}
}
我們需要在其它的組件下也添加這段代碼,當(dāng)然有快捷方式,就是在Android Studio的Project Structure中的signing去設(shè)置,它會(huì)自動(dòng)在build.gradle中生成相應(yīng)代碼。
組件化的介紹暫時(shí)就到這兒了,肯定是有許多地方是沒(méi)有講到的,就靠自己慢慢摸索啦~
下一篇文章講路由,Android 講解組件化-路由框架(2)
筆者水平有限,有寫得不好的地方,請(qǐng)大膽指出~
轉(zhuǎn)載請(qǐng)注明出處~