當一個工程愈來愈大,功能愈來愈複雜以後,成員愈來愈多的狀況下,如何維護一個巨大的安卓項目呢?php
第一階段,你們確定都是會把公共模塊什麼的都抽取出來,封裝成aar,以後經過maven的方式引入。java
第二階段,引入路由以及spi,把項目打散成一個個子module,而後每一個人負責一兩個模塊之類的,這樣就能保證並行開發了。android
第三階段,當項目臃腫到編譯速度愈來愈慢的狀況下。這個時候會先抽象一個殼工程,而後把因此的子項模塊用aar的方式引入這個殼,以後會把每一個業務放在一個倉庫內,這樣多個業務之間就不會出現代碼衝突之類的問題了。git
這個時候會出現另一些更困擾的問題。github
那麼有沒有現成的輪子能夠解決這些工程化以後會碰到的問題呢?json
Gradle Repo 容我給你們安利個項目,咱們當前項目使用的輪子就是這個。Github傳送門app
做者對於這個倉庫的描述是這樣的。maven
Gradle Repo是基於Gradle寫的一個插件,用於管理多個Git倉庫,支持方便快捷的切換分支。在根項目中會有一份配置清單repo.xml,用於描述模塊來源、工程結構以及依賴關係。gitlab
主要作了三件事情:post
從各個遠程倉庫clone代碼到指定目錄路徑下。經過Git的exclude而不是submodule。 動態include模塊,並模塊間的依賴關係,切換至指定分支。
文字描述上可能仍是有些不夠清晰哦,咱們經過一張做者的圖片去分析這個功能。
而後我本身寫了個mock的repo.xml的文件,咱們經過這個xml來簡單說下作了什麼。
<?xml version='1.0' encoding='UTF-8'?>
<manifest>
<substitute project=":module" targetModule="com.a.b:c"/>
<module name="RouterLib" origin="https://github.com/Leifzhang/Router-Android.git" srcBuild="false" substitute="com.github.leifzhang:routerLib" />
</manifest>
複製代碼
這個是我根據項目內生成的一個高度類似的模版。
當項目使用了Gradle Repo調整以後,咱們能夠隨意的拔插咱們須要的模塊,同時把多個模塊倉庫組合在一塊兒同時編譯。同時在ci上的則仍是經過implementation依賴的倉庫,咱們在開發的時候不會影響到別的業務線的開發,同時在不一樣的因爲每一個倉庫都是獨立的gitlab,因此在branch管理上也會有個自然的優點。
其實也不是,那麼因爲項目散落在不一樣的倉庫內,因此必然會出現一個問題,如何統一管理項目內的aar版本呢??????
不知道各位有沒有注意過前一陣子有個老哥寫的文章叫JakeWharton評價個人代碼像是在打地鼠?。其實jake大神說的configurations.all就是這裏的解決方案了。
那麼讓我給你們簡單的介紹下,configurations.all的做用就是強制拉平項目內的maven aar版本號。若是當項目經過implementation依賴引入了不一樣版本的aar的狀況下,會以configurations.all內定義的版本爲準,忽略掉項目內使用的差別版本。
configurations.all {
resolutionStrategy {
force "com.android.support:appcompat-v7:28.0.0"
}
}
複製代碼
上面的代碼的意思就是,強制項目內的supportv7版本到28.0.0版本上去。
若是簡單的使用configurations,仍是會出現每一個業務模塊都須要處理的狀況,沒法把這個能力收束到一個盒子內,這個時候咱們能夠考慮經過一個gradle plugin,自定義一個task的方式,對這個能力進行一次拓展。
首先咱們須要定義一份遠端的和branch版本相關的gradle文件,這個文件內能夠定義好咱們之前在工程目錄下所熟悉的maven倉庫的版本。
dep = [
fastjson : "com.alibaba:fastjson:${fastjsonVersion}",
//三方控件
androidSupportV4 : "com.android.support:support-v4:${androidSupportV4Version}",
androidSupportV7 : "com.android.support:appcompat-v7:${androidSupportV7Version}",
androidLifecycle : "android.arch.lifecycle:runtime:${androidLifecycleVersion}",
androidLifecycleCommon : "android.arch.lifecycle:common:${androidLifecycleVersion}",
androidLifecycleCommonJava8 : "android.arch.lifecycle:common-java8:${androidLifecycleVersion}",
androidLifecycleCompiler : "android.arch.lifecycle:compiler:${androidLifecycleVersion}",
androidLifecycleExtensions:"android.arch.lifecycle:extensions:${androidLifecycleVersion}",
recyclerview : "com.android.support:recyclerview-v7:${recyclerviewVersion}",
androidSupportAnnotations: "com.android.support:support-annotations:${androidSupportVersion}"
]
複製代碼
而後咱們自定義一個gradle插件,而後生成一個本身的task任務,同步命令被執行的時候,咱們就經過接口調用或者git操做的方式去獲取遠端的gradle,而後更改項目的gralde configurations.all的方式,去吧項目內的aar版本拉平。
class AATask : DefaultTask() {
@TaskAction
fun apply() {
##僞代碼 從遠端拉取Dep配置
//強制更換項目內配置
forceConfigVersion(project)
}
fun forceConfigVersion(project: Project) {
project.subprojects {
val depModuleSelectorNotations = mutableListOf<String>()
project.extensions.extraProperties.properties.forEach { key, any ->
if (any!=null && key!=null&&key.endsWith("dep")){
if (any is Map<*, *>){
collectDepModuleVersionSelectorNotations(depModuleSelectorNotations, any)
}
}
}
it.configurations.all { configuration ->
configuration.resolutionStrategy.force(depModuleSelectorNotations)
}
}
}
複製代碼
具體詳細的內容涉及到公司代碼就不和你們詳細的展開了,思路核心就是一切三方庫的版本以遠端的branch做爲標準。
本文只是一篇科普文章,並不涉及到任何代碼分析,若是有什麼得罪的地方,你也打不到我。