問題:實(shí)際業(yè)務(wù)變化快,而工程內(nèi)各個(gè)功能模塊耦合度太高哥桥,不能對功能模塊進(jìn)行快速方便地拆分或組裝拟糕。團(tuán)隊(duì)共同開發(fā)中倦踢,可能一個(gè)文件同時(shí)被多人修改辱挥,導(dǎo)致每次更新提交代碼都需要消耗大量時(shí)間去merge代碼。每次修改褂微,都需要進(jìn)行功能測試和系統(tǒng)測試宠蚂。
目的:解決以上問題求厕,使項(xiàng)目可以靈活配置,功能模塊完全解耦旅东,實(shí)踐組件化之路抵代。
實(shí)現(xiàn):在之前的開發(fā)中忘嫉,一個(gè)應(yīng)用程序庆冕,我們將全部功能模塊都寫在工程app包中。實(shí)踐組件化晦嵌,我們將各個(gè)功能模塊獨(dú)立出來惭载,最終以依賴包的形式整合到app主Module中去响巢。在這里我寫了個(gè)項(xiàng)目demo,簡單分了幾個(gè)功能模塊含长,應(yīng)用結(jié)構(gòu)如下圖所示:
說明:每一個(gè)組件module是一個(gè)子工程拘泞,子工程可以依賴基礎(chǔ)庫baselibrary可獨(dú)立運(yùn)行陪腌;也可以作為主工程的依賴庫铡原。
具體實(shí)現(xiàn):1:配置項(xiàng)目的buildscript,如下圖所示:
關(guān)于butterknife的配置及用法:http://jakewharton.github.io/butterknife,butterknife8支持在lib庫中注解卵洗。
2:在主app module gradle中如下配置:
applyplugin:'com.android.application'
applyplugin:'android-apt'
android {
? ? compileSdkVersion COMPILE_SDK_VERSION as int
? ? buildToolsVersion BUILD_TOOLS_VERSION
? ? defaultConfig {
? ? ? ? applicationId APPLICATION_ID
? ? ? ? minSdkVersion MIN_SDK_VERSIONas int
? ? ? ? targetSdkVersion TARGET_SDK_VERSIONas int
? ? ? ? versionCode 1
? ? ? ? versionName "1.0"
? ? }
? ? signingConfigs {
? ? ? ? debugConfig {
? ? ? ? ? ? storeFile file("***.jks")
? ? ? ? ? ? storePassword "******"
? ? ? ? ? ? keyAlias "*****"
? ? ? ? ? ? keyPassword "******"
? ? ? ? }
? ? releaseConfig {
? ? ? ? storeFile file("******.jks")
? ? ? ? storePassword "********"
? ? ? ? keyAlias "*****"
? ? ? ? keyPassword"*******"
? ? }
}
}
?buildTypes {
? ? ? ?release {
? ? ? ? ?minifyEnabled false
? ? ? ? ?proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
? ? ?}
? }
dependencies {
if(!isDebug.toBoolean()) {//各個(gè)模塊作為庫加載
compile project(':loginmodule')
compile project(':startmodule')
compile project(':homemodule')
compile project(':msgmodule')
}else{//各模塊獨(dú)立運(yùn)行
compile project(':baselibrary')
}
//router
apt'com.github.mzule.activityrouter:compiler:1.1.7'
}
說明:關(guān)于activityrouter的配置及使用十绑,在后面會(huì)說到本橙。
3:baselibrary作為各個(gè)模塊共同依賴的基礎(chǔ)庫脆诉,其gradle配置如下:
applyplugin:'com.android.library'
applyplugin:'com.jakewharton.butterknife'
applyplugin:'android-apt'
android {
compileSdkVersion24
buildToolsVersion"25.0.2"
defaultConfig {
minSdkVersion15
targetSdkVersion24
versionCode1
versionName"1.0"
}
buildTypes {
release {
minifyEnabledfalse
proguardFiles getDefaultProguardFile('proguard-android.txt'),'proguard-rules.pro'
}
}
}
dependencies {
compile fileTree(include: ['*.jar'],dir:'libs')
androidTestCompile('com.android.support.test.espresso:espresso-core:2.2.2', {
excludegroup:'com.android.support',module:'support-annotations'
})
compile'com.android.support:appcompat-v7:24.2.1'
compile'com.jakewharton:butterknife:8.5.1'
apt'com.jakewharton:butterknife-compiler:8.5.1'
compile'com.github.mzule.activityrouter:activityrouter:1.2.2'
}
4:在子工程模塊gradle配置如下(以homemodule為例):
if(isDebug.toBoolean()) {
applyplugin:'com.android.application'
}else{
applyplugin:'com.android.library'
}
applyplugin:'com.jakewharton.butterknife'
applyplugin:'android-apt'
android {
compileSdkVersion24
buildToolsVersion"25.0.2"
defaultConfig {
minSdkVersion15
targetSdkVersion24
versionCode1
versionName"1.0"
testInstrumentationRunner"android.support.test.runner.AndroidJUnitRunner"
}
buildTypes {
release {
minifyEnabledfalse
proguardFiles getDefaultProguardFile('proguard-android.txt'),'proguard-rules.pro'
}
}
sourceSets {
main{
if(isDebug.toBoolean()) {
manifest.srcFile'src/debug/AndroidManifest.xml'
}else{
manifest.srcFile'src/release/AndroidManifest.xml'
}
}
}
resourcePrefix"home_"
}
dependencies {
compile fileTree(dir:'libs',include: ['*.jar'])
androidTestCompile('com.android.support.test.espresso:espresso-core:2.2.2', {
excludegroup:'com.android.support',module:'support-annotations'
})
compile project(':baselibrary')
apt'com.jakewharton:butterknife-compiler:8.5.1'
//router
apt'com.github.mzule.activityrouter:compiler:1.1.7'
}
說明:當(dāng)module單獨(dú)運(yùn)行和作為module運(yùn)行時(shí)亏狰,其activity在manifest中設(shè)置也會(huì)不同暇唾,這里可以根據(jù)isDebug設(shè)置不同的manifest策州。當(dāng)分別開發(fā)模塊時(shí)宫仗,容易出資源重復(fù)命名的問題,可以在build.gradle中設(shè)置resourcePrefix "home_"下硕,通過給模塊設(shè)置不同的資源前綴梭姓,可以避免重復(fù)命名嫩码。
Activity跳轉(zhuǎn)問題
從上面的配置中,可以看到铡恕,項(xiàng)目引入了apt'com.github.mzule.activityrouter:compiler:1.1.7'探熔,我們?yōu)槭裁词褂肁ctivityRouter呢烘挫,當(dāng)我們把各個(gè)功能模塊抽成獨(dú)立的lib的時(shí)候,各個(gè)模塊之間難免要進(jìn)行Activity的跳轉(zhuǎn)及傳參苛蒲。我們不能再像以前那樣直接通過startActivity來實(shí)現(xiàn)跳轉(zhuǎn)了绿满。關(guān)于ActivityRouter的配置及用法:https://github.com/mzule/ActivityRouter
使用在application中注解:@Modules({"app","homeModule","loginModule","startModule","msgModule"})
public class XxxxApplication extends Application {
}
每個(gè)module中創(chuàng)建空java類注解:
@Module("homeModule")
public class HomeModule{
}
組件間通信問題:
不同組件Activity之間傳遞大量數(shù)據(jù)時(shí)可以通過EventBus來進(jìn)行傳遞喇颁,EventBus原理及用法:https://github.com/greenrobot/EventBus
編譯運(yùn)行
當(dāng)在gradle.properties中設(shè)置isDebug=true時(shí),可以獨(dú)立運(yùn)行每個(gè)module漾肮,獨(dú)立運(yùn)行調(diào)試克懊,當(dāng)設(shè)置isDebug=false七蜘,可以編譯運(yùn)行整個(gè)project,注意isDebug變量設(shè)置改變時(shí)橡卤,要重新對gradle進(jìn)行sync。
可能遇到的一些問題:
1:如果遇到/com/github/mzule/activityrouter/router/RouterInit.java javaError:(7, 5) 錯(cuò)誤: 找不到符號(hào) 符號(hào):? 變量 RouterMapping等錯(cuò)誤柜与,請檢查app是否把各個(gè)Module都依賴進(jìn)來了弄匕。
2:使用butterknife注解時(shí)沽瞭,每個(gè)Module會(huì)對應(yīng)生成R2文件驹溃,即使在base庫里注解過了,Module也要重新注解亡哄,組件中不能直接使用磺平。
3:如果項(xiàng)目中使用到menu注意:
@Override
protected void onMenuItemClick(MenuItem item) {
//? ? ? ? switch (item.getItemId()) {
//? ? ? ? ? ? case R2.id.xxx:
//? ? ? ? ? ? ? ? Routers.open(mContext,"");
//? ? ? ? ? ? ? ? break;
//? ? ? ? }
if (item.getItemId() == R.id.xxx){
Routers.open(mContext,"");
}
super.onMenuItemClick(item);
}
尋找對應(yīng)的menu id時(shí)拐辽,用if else 代替 switch,注:itemid 和 R2值不一樣菠劝,和R是一樣的赶诊。