組件化開發
參考資源
為什么要組件化開發
解決問題
- 實際業務變化非常快,但是單一工程的業務模塊耦合度太高,牽一發而動全身;
- 對工程所做的任何修改都必須要編譯整個工程;
- 功能測試和系統測試每次都要進行;
- 團隊協同開發存在較多的沖突.不得不花費更多的時間去溝通和協調,并且在開發過程中,任何一位成員沒辦法專注于自己的功能點,影響開發效率;
- 不能靈活的對業務模塊進行配置和組裝;
好處
- 加快業務迭代速度,各個業務模塊組件更加獨立,不再出現業務耦合情況;
- 穩定的公共模塊采用依賴庫方式,提供給各個業務線使用,減少重復開發和維護工作量;
- 迭代頻繁的業務模塊采用組件方式,各業務研發可以互不干擾、提升協作效率,并控制產品質量;
- 為新業務隨時集成提供了基礎,所有業務可上可下,靈活多變;
- 降低團隊成員熟悉項目的成本,降低項目的維護難度;
- 加快編譯速度,提高開發效率;
- 控制代碼權限,將代碼的權限細分到更小的粒度;
具體實現方案
1.組件模式和集成模式的轉換
android studio 中的Module主要又兩種屬性
-
application屬性,可以單獨運行的Android程序,也就是我們的APP
//這個是在build.gradle中進行設置的(就是最頂上那一行) apply plugin: 'com.android.application'
-
library屬性,不可以單獨運行,一般是Android程序依賴的庫文件
//這個是在build.gradle中進行設置的(就是最頂上那一行) apply plugin: ‘com.android.library’
組件化和集成模式的轉換
說到這里我不想去講解gradle的語法,因為我也不會,但是可以告訴你怎么去弄!!!
這里是引用張華洋的說明:博客地址
Module的屬性是在每個組件的 build.gradle 文件中配置的,當我們在組件模式開發時,業務組件應處于application屬性,這時的業務組件就是一個 Android App,可以獨立開發和調試;而當我們轉換到集成模式開發時,業務組件應該處于 library 屬性,這樣才能被我們的“app殼工程”所依賴,組成一個具有完整功能的APP;
但是我們如何讓組件在這兩種模式之間自動轉換呢?總不能每次需要轉換模式的時候去每個業務組件的 Gralde 文件中去手動把 Application 改成 library 吧?如果我們的項目只有兩三個組件那么這個辦法肯定是可行的,手動去改一遍也用不了多久,但是在大型項目中我們可能會有十幾個業務組件,再去手動改一遍必定費時費力,這時候就需要程序員發揮下懶的本質了。
試想,我們經常在寫代碼的時候定義靜態常量,那么定義靜態常量的目的什么呢?當一個常量需要被好幾處代碼引用的時候,把這個常量定義為靜態常量的好處是當這個常量的值需要改變時我們只需要改變靜態常量的值,其他引用了這個靜態常量的地方都會被改變,做到了一次改變,到處生效;根據這個思想,那么我們就可以在我們的代碼中的某處定義一個決定業務組件屬性的常量,然后讓所有業務組件的build.gradle都引用這個常量,這樣當我們改變了常量值的時候,所有引用了這個常量值的業務組件就會根據值的變化改變自己的屬性;可是問題來了?靜態常量是用Java代碼定義的,而改變組件屬性是需要在Gradle中定義的,Gradle能做到嗎?
Gradle自動構建工具有一個重要屬性,可以幫助我們完成這個事情。每當我們用AndroidStudio創建一個Android項目后,就會在項目的根目錄中生成一個文件 gradle.properties,我們將使用這個文件的一個重要屬性:在Android項目中的任何一個build.gradle文件中都可以把gradle.properties中的常量讀取出來;那么我們在上面提到解決辦法就有了實際行動的方法,首先我們在gradle.properties中定義一個常量值 isModule(是否是組件開發模式,true為是,false為否):
在gradle.properties中添加是否組件化的判斷
PS:首先gradle.properties這個文件有一個重要的功能:在Android項目中的任何一個build.gradle文件中都可以把gradle.properties中的常量讀取出來(但是讀取出來的時候是String格式的字符串,這一點要切記)
在gradle.properties中添加
# 是否組件化的標識,注意啊這里要用"#"號注釋
isModule = false
然后在相應的Module中的build.gradle去添加相應的邏輯
//這里說明一下就是如果是組件化的
if (isModule.toBoolean()) {
apply plugin: 'com.android.application'
} else {
apply plugin: 'com.android.library'
}
這樣寫完了之后就會在每次改變*isModule賦值的化就可以更改相應的模塊是否能單獨運行了(為了保證單獨組件的單獨運行,會創建一個公用的Module,存放網絡請求或者圖片處理等一些公共的資源,從而確保module的單獨運行)
組件之間AndroidManifest合并問題
這里是引用張華洋的說明:博客地址
但是大家應該注意到這個問題是在組件開發模式和集成開發模式之間轉換引起的問題,而在上一節中我們已經解決了組件模式和集成模式轉換的問題,另外大家應該都經歷過將 Android 項目從 Eclipse 切換到 AndroidStudio 的過程,由于 Android 項目在 Eclipse 和 AndroidStudio開發時 AndroidManifest.xml 文件的位置是不一樣的,我們需要在build.gradle 中指定下 AndroidManifest.xml 的位置,AndroidStudio 才能讀取到 AndroidManifest.xml,這樣解決辦法也就有了,我們可以為組件開發模式下的業務組件再創建一個 AndroidManifest.xml,然后根據isModule指定AndroidManifest.xml的文件路徑,讓業務組件在集成模式和組件模式下使用不同的AndroidManifest.xml,這樣表單沖突的問題就可以規避了。
創建一個新的AndroidManifest.xml
具體的解決方案就是在相應的Module中在根路徑添加一個Module文件夾,直接創建一份AndroidManifest.xml,這里面的這個文件,直接像你平時寫項目一樣去寫就可以了
修改相應的build.gradle
在android標簽內創建
sourceSets {
main {
if (isModule.toBoolean()) {/*是組件化*/
manifest.srcFile 'src/main/AndroidManifest.xml'
java {/*集成開發模式下排除debug文件加中的所有java文件*/
exclude 'debug/**'//這個相應的debug文件是在java文件目錄下的
}
} else {
manifest.srcFile 'src/main/module/AndroidManifest.xml'
}
}
}
全局Context的獲取及組件數據初始化
其實我理解的全局Context的理解就是->先創建一個所有module都引用的一個module(common這個module是每個module都會引用的一個module,這里要處理重復的問題,后面補充),這個module就存放一些都能用到的東西,然后引入到module或者主項目中,這樣所有的module都會包含一些公共的內容:如請求網絡,圖片處理等一些相應的內容,這樣既保證了每個module的單獨運行,也保證了項目的耦合程度
這里有一個存在一個技巧,在前面沒有去理解,就是在組件之間AndroidManifest合并問題處有這樣一段代碼
java {/*集成開發模式下排除debug文件加中的所有java文件*/
exclude 'debug/**'
}
這段代碼的主要問題就是解決全局Context的問題,為什么呢???
我們想一下場景啊!當你某一個模塊單獨運行的時候,存在登陸獲取token的問題,但是你要是單獨運行的時候呢,可能這個模塊沒有token你怎么辦呢?其實解決辦法就是創建一個debug文件夾,這里呢可以自己創建一個相應的Application去請求登陸的接口這樣你的module單獨運行的時候就會有token了具體值
(這里我看張華洋的博客時我覺的處理挺好的,他在公共的類中去創建了一個BaseApplication所有module中的Application(在debug文件夾下創建的,但是要在清單文件中去配置啊!!!)都去繼承這個Application,這樣既解決了沒有Application的情況,又解決了集成打包時候多次創建Application的情況,覺得比較不錯所以借鑒一下)
上面那行代碼會在集成開發模式的情況下把debug文件夾下的內容刪除,這里就成功的解決了單獨運行的token問題,也解決了集成打包的時候會出現多個Application的問題
library依賴問題
解決library的重復引用問題又兩種方式:
- 根據組件名稱排除
- 根據包名排除
dependencies {
compile fileTree(dir: 'libs', include: ['*.jar'])
compile("com.jude:easyrecyclerview:$rootProject.easyRecyclerVersion") {
exclude module: 'support-v4'//根據組件名排除
exclude group: 'android.support.v4'//根據包名排除
}
}
這里說明一點:基礎的控件一般都在common中去引用,然后住項目和其他的項目都導入common就可以了,但是這里應該存在一個問題就是Common存在導入多次的問題
其實在構建APP的過程中Gradle會自動將重復的arr包排除,APP中也就不會存在相同的代碼了;
組件之間的調用和通信
這里是引用張華洋的說明:博客地址
在組件化開發的時候,組件之間是沒有依賴關系,我們不能在使用顯示調用來跳轉頁面了,因為我們組件化的目的之一就是解決模塊間的強依賴問題,
假如現在要從A業務組件跳轉到業務B組件,并且要攜帶參數跳轉,這時候怎么辦呢?
而且組件這么多怎么管理也是個問題,這時候就需要引入“路由”的概念了,由本文開始的組件化模型下的業務關系圖可知路由就是起到一個轉發的作用。
這里我將介紹開源庫的“ActivityRouter” ,有興趣的同學情直接去ActivityRouter的Github主頁學習:ActivityRouter,ActivityRouter支持給Activity定義 URL,
這樣就可以通過 URL 跳轉到Activity,并且支持從瀏覽器以及 APP 中跳入我們的Activity,而且還支持通過 url 調用方法。
下面將介紹如何將ActivityRouter集成到組件化項目中以實現組件之間的調用;
這里涉及到路由的問題后續在進行補充
組件之間資源名稱沖突的問題
這里是引用張華洋的說明:博客地址
因為我們拆分出了很多業務組件和功能組件,在把這些組件合并到“app殼工程”時候就有可能會出現資源名沖突問題,
例如A組件和B組件都有一張叫做“ic_back”的圖標,這時候在集成模式下打包APP就會編譯出錯,解決這個問題最簡單的辦法就是在項目中約定資源文件命名規約,
比如強制使每個資源文件的名稱以組件名開始,這個可以根據實際情況和開發人員制定規則。當然了萬能的Gradle構建工具也提供了解決方法,
通過在在組件的build.gradle中添加如下的代碼:
```
//設置了resourcePrefix值后,所有的資源名必須以指定的字符串做前綴,否則會報錯。
//但是resourcePrefix這個值只能限定xml里面的資源,并不能限定圖片資源,所有圖片資源仍然需要手動去修改資源名。
resourcePrefix "girls_"
```
但是設置了這個屬性后有個問題,所有的資源名必須以指定的字符串做前綴,否則會報錯,
而且resourcePrefix這個值只能限定xml里面的資源,并不能限定圖片資源,所有圖片資源仍然需要手動去修改資源名;
所以我并不推薦使用這種方法來解決資源名沖突。
2.組件化項目的工程類型
在組件化工程模型中主要有:app殼工程、業務組件和功能組件3種類型,而業務組件中的Main組件和功能組件中的Common組件比較特殊,下面將分別介紹。
1.app殼工程
app殼工程相當于一個空殼的項目,沒有任何業務代碼,也不能又Activity,但是它又必須單獨劃分一個組件,而且不能融合其他組件中;
因為它又幾點重要的功能:
app殼工程中聲明了我們Android應用的Application 但是這個Application必須是繼承Common組件中的BaseApplication(如果無需事先自己的Application可以直接在表單生命BaseApplication),
因為只有這樣,在打包應用后才能讓BaseApplication中的Context生效,當然你也可以在這個Application中初始化我們工程中使用的庫文件,還可以在這里面解決Android引用方法數超過65535的限制,
對于崩潰事件的捕獲和發送也可以在這里面聲明app殼工程的AndroidManifest.xml是我們Android應用的根表單 應用的名,圖標依稀是否支持備份等等屬性都是在這份表單中配置的,
其他組件中的表單最終在集成開發模式下都被合并到這份AndroidManifest.xml中app殼工程的build.gradle是比較特殊的 app殼不管是在集成開發模式還是組件開發模式,它的屬性始終都是:
com.android.application,因為最終其它的組件都要被app殼工程所依賴,被打包進app殼工程中,這一點從組件化工程模型圖中就能體現出來,
所以app殼工程是不需要單獨調試單獨開發的.另外Android應用的打包簽名,以及build.gradle和defaultConfig都需要在這里面配置,
而它的dependencies則需要根據isModule的值分別依賴不同的組件,在組件開發模式下app殼工程只需要依賴Common組件,
或者為了防止報錯也可以根據實際情況依賴其他功能組件,而在集成模式下app殼工程必須依賴所有在應用Application中聲明的業務組件,并且不需要再依賴任何功能組件。
這里是引用張華洋的說明:博客地址
一份殼工程的build.gradle文件
apply plugin: 'com.android.application'
static def buildTime() {
return new Date().format("yyyyMMdd");
}
android {
signingConfigs {
release {
keyAlias 'guiying712'
keyPassword 'guiying712'
storeFile file('/mykey.jks')
storePassword 'guiying712'
}
}
compileSdkVersion rootProject.ext.compileSdkVersion
buildToolsVersion rootProject.ext.buildToolsVersion
defaultConfig {
applicationId "com.guiying.androidmodulepattern"
minSdkVersion rootProject.ext.minSdkVersion
targetSdkVersion rootProject.ext.targetSdkVersion
versionCode rootProject.ext.versionCode
versionName rootProject.ext.versionName
multiDexEnabled false
//打包時間
resValue "string", "build_time", buildTime()
}
buildTypes {
release {
//更改AndroidManifest.xml中預先定義好占位符信息
//manifestPlaceholders = [app_icon: "@drawable/icon"]
// 不顯示Log
buildConfigField "boolean", "LEO_DEBUG", "false"
//是否zip對齊
zipAlignEnabled true
// 縮減resource文件
shrinkResources true
//Proguard
minifyEnabled true
proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
//簽名
signingConfig signingConfigs.release
}
debug {
//給applicationId添加后綴“.debug”
applicationIdSuffix ".debug"
//manifestPlaceholders = [app_icon: "@drawable/launch_beta"]
buildConfigField "boolean", "LOG_DEBUG", "true"
zipAlignEnabled false
shrinkResources false
minifyEnabled false
debuggable true
}
}
}
dependencies {
compile fileTree(dir: 'libs', include: ['*.jar'])
annotationProcessor "com.github.mzule.activityrouter:compiler:$rootProject.annotationProcessor"
if (isModule.toBoolean()) {
compile project(':lib_common')
} else {
compile project(':module_main')
compile project(':module_girls')
compile project(':module_news')
}
}
2.功能組件和Common組件
功能組件是為了支撐業務組件的某些功能而獨立劃分出來的組件,功能組件和第三方庫是一樣的,
擁有如下特征:
功能組件
功能組件的AndroidManifest.xml是一張空表,這張表只有功能組件的包名;
功能組件不管是在集成開發還是組件開發模式下屬性始終是:com.android.library,
所以功能組件不需要讀取gradle.properties 中的isModule值的;另外功能組件的build.gradle也無需設置buildType是,
只需要dependencies這個共鞥組件需要的jar包和開源庫.
這里是引用張華洋的說明:博客地址
一份 普通 的功能組件的 build.gradle文件:
apply plugin: 'com.android.library'
android {
compileSdkVersion rootProject.ext.compileSdkVersion
buildToolsVersion rootProject.ext.buildToolsVersion
defaultConfig {
minSdkVersion rootProject.ext.minSdkVersion
targetSdkVersion rootProject.ext.targetSdkVersion
versionCode rootProject.ext.versionCode
versionName rootProject.ext.versionName
}
}
dependencies {
compile fileTree(dir: 'libs', include: ['*.jar'])
}
Common組件
Common組件除了有功能組件的普遍屬性外,還具有其他功能:
- Common組件的 AndroidManifest.xml 不是一張空表,這張表中聲明了我們 Android應用用到的所有使用權限 uses-permission 和 uses-feature,放到這里是因為在組件開發模式下,所有業務組件就無需在自己的 AndroidManifest.xm 聲明自己要用到的權限了。
- Common組件的 build.gradle 需要統一依賴業務組件中用到的 第三方依賴庫和jar包,例如我們用到的ActivityRouter、Okhttp等等。
- Common組件中封裝了Android應用的 Base類和網絡請求工具、圖片加載工具等等,公用的 widget控件也應該放在Common 組件中;業務組件中都用到的數據也應放于Common組件中,例如保存到 SharedPreferences 和 DataBase 中的登陸數據;
- Common組件的資源文件中需要放置項目公用的 Drawable、layout、sting、dimen、color和style 等等,另外項目中的 Activity 主題必須定義在 Common中,方便和 BaseActivity 配合保持整個Android應用的界面風格統一。
這里是引用張華洋的說明:博客地址
一份 Common 的功能組件的 build.gradle文件:
apply plugin: 'com.android.library'
android {
compileSdkVersion rootProject.ext.compileSdkVersion
buildToolsVersion rootProject.ext.buildToolsVersion
defaultConfig {
minSdkVersion rootProject.ext.minSdkVersion
targetSdkVersion rootProject.ext.targetSdkVersion
versionCode rootProject.ext.versionCode
versionName rootProject.ext.versionName
}
}
dependencies {
compile fileTree(dir: 'libs', include: ['*.jar'])
//Android Support
compile "com.android.support:appcompat-v7:$rootProject.supportLibraryVersion"
compile "com.android.support:design:$rootProject.supportLibraryVersion"
compile "com.android.support:percent:$rootProject.supportLibraryVersion"
//網絡請求相關
compile "com.squareup.retrofit2:retrofit:$rootProject.retrofitVersion"
compile "com.squareup.retrofit2:retrofit-mock:$rootProject.retrofitVersion"
compile "com.github.franmontiel:PersistentCookieJar:$rootProject.cookieVersion"
//穩定的
compile "com.github.bumptech.glide:glide:$rootProject.glideVersion"
compile "com.orhanobut:logger:$rootProject.loggerVersion"
compile "org.greenrobot:eventbus:$rootProject.eventbusVersion"
compile "com.google.code.gson:gson:$rootProject.gsonVersion"
compile "com.github.chrisbanes:PhotoView:$rootProject.photoViewVersion"
compile "com.jude:easyrecyclerview:$rootProject.easyRecyclerVersion"
compile "com.github.GrenderG:Toasty:$rootProject.toastyVersion"
//router
compile "com.github.mzule.activityrouter:activityrouter:$rootProject.routerVersion"
}
3.業務組件和Main組件
業務組件
業務組件就是根據業務邏輯的不同拆分出來的組件,業務組件的特征如下:
- 業務組件中要有兩張AndroidManifest.xml,分別對應組件開發模式和集成開發模式,這兩張表的區別請查看 組件之間AndroidManifest合并問題 小節。
- 業務組件在集成模式下是不能有自己的Application的,但在組件開發模式下又必須實現自己的Application并且要繼承自Common組件的BaseApplication,并且這個Application不能被業務組件中的代碼引用,因為它的功能就是為了使業務組件從BaseApplication中獲取的全局Context生效,還有初始化數據之用。
- 業務組件有debug文件夾,這個文件夾在集成模式下會從業務組件的代碼中排除掉,所以debug文件夾中的類不能被業務組件強引用,例如組件模式下的 Application 就是置于這個文件夾中,還有組件模式下開發給目標 Activity 傳遞參數的用的 launch Activity 也應該置于 debug 文件夾中;
- 業務組件必須在自己的 Java文件夾中創建業務組件聲明類,以使 app殼工程 中的 應用Application能夠引用,實現組件跳轉,具體請查看 組件之間調用和通信 小節;
- 業務組件必須在自己的 build.gradle 中根據 isModule 值的不同改變自己的屬性,在組件模式下是:com.android.application,而在集成模式下com.android.library;同時還需要在build.gradle配置資源文件,如 指定不同開發模式下的AndroidManifest.xml文件路徑,排除debug文件夾等;業務組件還必須在dependencies中依賴Common組件,并且引入ActivityRouter的注解處理器annotationProcessor,以及依賴其他用到的功能組件。
這里是引用張華洋的說明:博客地址
一份普通業務組件的 build.gradle文件:
if (isModule.toBoolean()) {
apply plugin: 'com.android.application'
} else {
apply plugin: 'com.android.library'
}
android {
compileSdkVersion rootProject.ext.compileSdkVersion
buildToolsVersion rootProject.ext.buildToolsVersion
defaultConfig {
minSdkVersion rootProject.ext.minSdkVersion
targetSdkVersion rootProject.ext.targetSdkVersion
versionCode rootProject.ext.versionCode
versionName rootProject.ext.versionName
}
sourceSets {
main {
if (isModule.toBoolean()) {
manifest.srcFile 'src/main/module/AndroidManifest.xml'
} else {
manifest.srcFile 'src/main/AndroidManifest.xml'
//集成開發模式下排除debug文件夾中的所有Java文件
java {
exclude 'debug/**'
}
}
}
}
//設置了resourcePrefix值后,所有的資源名必須以指定的字符串做前綴,否則會報錯。
//但是resourcePrefix這個值只能限定xml里面的資源,并不能限定圖片資源,所有圖片資源仍然需要手動去修改資源名。
//resourcePrefix "girls_"
}
dependencies {
compile fileTree(dir: 'libs', include: ['*.jar'])
annotationProcessor "com.github.mzule.activityrouter:compiler:$rootProject.annotationProcessor"
compile project(':lib_common')
}
Main組件
Main組件集成模式下的AndroidManifest.xml是跟其他業務組件不一樣的,Main組件的表單中聲明了我們整個Android應用的launch Activity,這就是Main組件的獨特之處;所以我建議SplashActivity、登陸Activity以及主界面都應屬于Main組件,也就是說Android應用啟動后要調用的頁面應置于Main組件。
這里是引用張華洋的說明:博客地址
一份Main業務組件的 build.gradle文件:
<activity
android:name=".splash.SplashActivity"
android:launchMode="singleTop"
android:screenOrientation="portrait"
android:theme="@style/SplashTheme">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
3.組件化項目的混淆方案
組件化項目的Java代碼混淆方案采用在集成模式下集中在app殼工程中混淆,各個業務組件不配置混淆文件。 集成開發模式下在app殼工程中build.gradle文件的release構建類型中開啟混淆屬性,其他buildTypes配置方案跟普通項目保持一致,Java混淆配置文件也放置在app殼工程中,各個業務組件的混淆配置規則都應該在app殼工程中的混淆配置文件中添加和修改。
之所以不采用在每個業務組件中開啟混淆的方案,是因為 組件在集成模式下都被 Gradle 構建成了 release 類型的arr包,一旦業務組件的代碼被混淆,而這時候代碼中又出現了bug,將很難根據日志找出導致bug的原因;另外每個業務組件中都保留一份混淆配置文件非常不便于修改和管理,這也是不推薦在業務組件的 build.gradle 文件中配置 buildTypes (構建類型)的原因。
4.工程的build.gradle和gradle.properties文件
組件化工程的build.gradle文件
在組件化項目中因為每個組件的 build.gradle 都需要配置 compileSdkVersion、buildToolsVersion和defaultConfig 等的版本號,而且每個組件都需要用到 annotationProcessor,為了能夠使組件化項目中的所有組件的 build.gradle 中的這些配置都能保持統一,并且也是為了方便修改版本號,我們統一在Android工程根目錄下的build.gradle中定義這些版本號,當然為了方便管理Common組件中的第三方開源庫的版本號,最好也在這里定義這些開源庫的版本號,然后在各個組件的build.gradle中引用Android工程根目錄下的build.gradle定義的版本號,組件化工程的 build.gradle 文件代碼如下:
這里是引用張華洋的說明:博客地址
buildscript {
repositories {
jcenter()
mavenCentral()
}
dependencies {
//classpath "com.android.tools.build:gradle:$localGradlePluginVersion"
//$localGradlePluginVersion是gradle.properties中的數據
classpath "com.android.tools.build:gradle:$localGradlePluginVersion"
}
}
allprojects {
repositories {
jcenter()
mavenCentral()
//Add the JitPack repository
maven { url "https://jitpack.io" }
//支持arr包
flatDir {
dirs 'libs'
}
}
}
task clean(type: Delete) {
delete rootProject.buildDir
}
// Define versions in a single place
//時間:2017.2.13;每次修改版本號都要添加修改時間
ext {
// Sdk and tools
//localBuildToolsVersion是gradle.properties中的數據
buildToolsVersion = localBuildToolsVersion
compileSdkVersion = 25
minSdkVersion = 16
targetSdkVersion = 25
versionCode = 1
versionName = "1.0"
javaVersion = JavaVersion.VERSION_1_8
// App dependencies version
supportLibraryVersion = "25.3.1"
retrofitVersion = "2.1.0"
glideVersion = "3.7.0"
loggerVersion = "1.15"
eventbusVersion = "3.0.0"
gsonVersion = "2.8.0"
photoViewVersion = "2.0.0"
//需檢查升級版本
annotationProcessor = "1.1.7"
routerVersion = "1.2.2"
easyRecyclerVersion = "4.4.0"
cookieVersion = "v1.0.1"
toastyVersion = "1.1.3"
}
組件化工程的gradle.properties文件
在組件化實施流程中我們了解到gradle.properties有兩個屬性對我們非常有用:
- 在Android項目中的任何一個build.gradle文件中都可以把gradle.properties中的常量讀取出來,不管這個build.gradle是組件的還是整個項目工程的build.gradle;
- gradle.properties中的數據類型都是String類型,使用其他數據類型需要自行轉換;
利用gradle.properties的屬性不僅可以解決集成開發模式和組件開發模式的轉換,而且還可以解決在多人協同開發Android項目的時候,因為開發團隊成員的Android開發環境(開發環境指Android SDK和AndroidStudio)不一致而導致頻繁改變線上項目的build.gradle配置。
在每個Android組件的 build.gradle 中有一個屬性:buildToolsVersion,表示構建工具的版本號,這個屬性值對應 AndroidSDK 中的 Android SDK Build-tools,正常情況下 build.gradle 中的 buildToolsVersion 跟你電腦中 Android SDK Build-tools 的最新版本是一致的,比如現在 Android SDK Build-tools 的最新的版本是:25.0.3,那么我的Android項目中 build.gradle 中的 buildToolsVersion 版本號也是 25.0.3,但是一旦一個Android項目是由好幾個人同時開發,總會出現每個人的開發環境 Android SDK Build-tools 是都是不一樣的,并不是所有人都會經常升級更新 Android SDK,而且代碼是保存到線上環境的(例如使用 SVN/Git 等工具),某個開發人員提交代碼后線上Android項目中 build.gradle 中的 buildToolsVersion 也會被不斷地改變。
另外一個原因是因為Android工程的根目錄下的 build.gradle 聲明了 Android Gradle 構建工具,而這個工具也是有版本號的,而且 Gradle Build Tools 的版本號跟 AndroidStudio 版本號一致的,但是有些開發人員基本很久都不會升級自己的 AndroidStudio 版本,導致團隊中每個開發人員的 Gradle Build Tools 的版本號也不一致。
如果每次同步代碼后這兩個工具的版本號被改變了,開發人員可以自己手動改回來,并且不要把改動工具版本號的代碼提交到線上環境,這樣還可以勉強繼續開發;但是很多公司都會使用持續集成工具(例如Jenkins)用于持續的軟件版本發布,而Android出包是需要 Android SDK Build-tools 和 Gradle Build Tools 配合的,一旦提交到線上的版本跟持續集成工具所依賴的Android環境構建工具版本號不一致就會導致Android打包失敗。
為了解決上面問題就必須將Android項目中 build.gradle 中的 buildToolsVersion 和 GradleBuildTools 版本號從線上代碼隔離出來,保證線上代碼的 buildToolsVersion 和 Gradle Build Tools 版本號不會被人為改變。
具體的實施流程大家可以查看這篇博文: AndroidStudio本地化配置gradle的buildToolsVersion和gradleBuildTools
上面這些要感謝章華洋的博客,基本是按照他的寫法自己寫了一遍,體會了一下,里面的只是還是很多了,僅作備份,如果樓主有意見,馬上刪除!!!