筆者最近接受了 躺平
(不是等死),換了一份新工做。html
這部份內容,也是從前東家的 實際狀況
出發的,惋惜沒法親手去推廣落地了。java
在前段時間,我發佈過一篇拙見:三思系列:組件化場景下module依賴優雅實踐方案, 該文在組件化背景下,探索了一種方案,能夠同時知足 減小編譯數量以減小編譯時間
、便捷的修改依賴樹以靈活改動任意層級的Module內容
。 具體內容能夠閱讀前文,再也不贅述android
除卻Module依賴,還有 庫包依賴
,本文着重於探索 庫包依賴項
的管理方式,並且是狹義上的 倉庫下的庫包
編程
並 斗膽
稱之爲 最佳實踐
。後端
首先肯定一件事情:markdown
implementation fileTree(dir: 'libs', include: ['*.jar'])
複製代碼
此類方式,引入的庫包不屬於 倉庫
範疇,僅討論基於Maven倉庫的範疇,贅述一句,倉庫按照習慣又能夠分爲兩種類型:網絡
固然,這並不影響本文的討論app
衆所周知,使用Gradle肯定倉庫的庫包須要三個因素:框架
最新
的含義for example:運維
androidx.core:core-ktx:1.3.2
複製代碼
以Android爲例,商業項目中,一個Project僅存在一個Module
的狀況應該 很是少見 了, 每每一個Project下會存在多個Module,並且存在必定的依賴關係。
若是沒有合適的管理手段,那麼每一個Module均聲明自身的依賴項,當發生版本變動時:
修改過於零碎
同一個依賴項在不一樣Module下可能出現版本差別
,這也是上一點所帶來的後果
舉個更典型的例子,以 後端項目爲例,微服務
的概念你們必定不陌生.
即便不曾深刻了解,也知道後端將整個服務體系進行了拆分,用多個子系統項目(微服務)共同 支撐完整的服務體系。 以此達到 下降複雜度、 根據業務特性使用不一樣框架、 根據業務權重定製運維策略 等目的
而微服務之間經過RPC進行通訊,而此處勢必牽涉一個最大的 痛點
:Service方法簽名和DTO數據保持一致
,不然會帶來 方法不存在
或者 數據遺失、解析錯誤
等問題。
比較早期的作法,是在Gradle構建時的運行環境中,建立或者利用Project級別的集合對象,將依賴項信息所有寫入其中,各個Module使用時,達成了統一。
你們對這種作法很熟悉,再也不用代碼舉例。 每每須要用到Extension擴展,爲了方便描述,咱們將:存儲依賴項信息的Project級別集合
稱爲 Ext.deps
優勢:
缺點:
新版本提示
利用Gradle 能夠apply 遠程構建腳本 (xxx.gradle) 的特性,進行方案改進。
將 "構建 Ext.deps 信息" 的 腳本
,存儲於網絡特定位置,以解決多Project難以管理的問題。
通常須要對腳本文件按照版本命名,並保有全部版本的腳本。
這樣能夠避免:項目回溯版本功能時,出現額外問題。
Gradle編譯項目是頗有意思的事情,咱們知道:在成功加載完Gradle項目後,會 編譯Gradle腳本
並生成各種Gradle任務,實際狀況會更加複雜,爲了方便,咱們將之稱爲 Task編譯
既然存在編譯過程,Gradle團隊索性留了一個後門:
若是根項目下存在"buildSrc", gradle 認爲這是在Task編譯過程當中須要編譯的內容,這些內容可能包含了:
- Gradle插件內容
- 插件設置內容
- 等等
而且其編譯結果對於該項目下的Gradle內容透明
這並非一個新的特性,它至少已經有五年的歷史了
Gradle官方指導文檔 ,官方文檔對其使用方式作了概要的描述。
由於buildSrc機制已經不是一個新特性了,故而利用這個機制去 管理Gradle依賴信息
已是一個老話題了。
多是巧合
,該作法出如今開發者視野中時,恰好是 gradle開始對 kotlin-dsl
進行支持,一樣不是新特性,大約是三年前的Gradle-4.10。
而開始流行的作法又剛好對新特性進行了嚐鮮,而且在講解視頻中留下了一些坑,因而這一作法的着重點,便被吸引到了 如何正確使用kotlin管理Gradle項目的依賴項
這一話題上。
這一作法和kotlin、kts腳本並沒有實質關聯
在buildSrc目錄下,按照標準sourceSet結構創建目錄,並新增類文件例如:
buildSrc/src/main/java/Deps.java
public class Deps {
public static String junit = "junit:junit:4.13.0";
}
複製代碼
sync後,類會被編譯,咱們能夠在項目下的Gradle腳本中,只用使用,例如:
dependencies {
//...
testImplementation Deps.junit
// 'junit:junit:4.+'
androidTestImplementation 'androidx.test.ext:junit:1.1.2'
androidTestImplementation 'androidx.test.espresso:espresso-core:3.3.0'
}
複製代碼
而且能夠享有 代碼提示
、 跳轉
、 javaDoc彈窗
功能
而可查詢到的常見作法,每每是使用kotlin類,那麼就須要讓buildSrc 在編譯時支持kotlin
,那麼天然須要 添加插件
:
在buildSrc下新建 build.gradle
並添加插件:
apply plugin: "kotlin"
buildscript {
ext.kotlin_version = "1.4.21"
repositories {
jcenter()
}
dependencies {
classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version"
}
}
repositories {
jcenter()
}
複製代碼
便可,此時添加的kotlin類便可被編譯。
buildSrc/src/main/java/KDeps.kt
object KDeps {
@JvmStatic
val ext_junit = "androidx.test.ext:junit:1.1.2"
}
複製代碼
使用示例:
dependencies {
testImplementation Deps.junit
// 'junit:junit:4.+'
androidTestImplementation KDeps.ext_junit
//'androidx.test.ext:junit:1.1.2'
androidTestImplementation 'androidx.test.espresso:espresso-core:3.3.0'
}
複製代碼
一樣能夠享有 代碼提示
、 跳轉
、 javaDoc彈窗
功能
而網傳的 kts腳本
以及添加 kotlin-dsl
支持,其實在這個需求中,並沒有真正的有效用途,只不過是應用了kts腳本後, 自己就須要編譯kotlin內容,因此 默認使用了kotlin編譯插件
言歸正傳,使用這種管理方式後,咱們解決了無代碼提示的弊端,再次 利用機器解放生產力
。
可是,咱們沒有解決服務端例子中的問題
我想你已經深入意識到了buildSrc機制的本質是啥:
利用Gradle 編譯 buildSrc內容,產物供
後續的
該項目的
Gradle編譯過程
使用
那麼你必定能夠想到,buildSrc能夠申明自身的依賴!
因而,咱們對經常使用庫包進行分析後,選取對象並肯定版本後,便可編寫一個Library,
這是最簡單的作法,便可在多個Project下,以最小的人力成本管理依賴並知足 一致性需求
Library依賴 Gradle後,能夠編寫 Gradle-Task內容配置 的過程代碼,封裝 依賴添加
和 依賴檢查
等內容。
舉個簡單的例子:
object KDeps {
// @JvmStatic
const val ext_junit = "androidx.test.ext:junit:1.1.2"
}
複製代碼
public class Deps {
public static String junit = "junit:junit:4.13.0";
public static void applyAll(Project project) {
project.getDependencies().add(
"testImplementation", junit
);
project.getDependencies().add(
"androidTestImplementation",KDeps.ext_junit
);
}
}
複製代碼
buildSrc/build.gradle
apply plugin: "kotlin"
buildscript {
ext.kotlin_version = "1.4.21"
repositories {
jcenter()
}
dependencies {
classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version"
// implementation 'com.android.tools.build:gradle:4.1.1'
//gradle sdk
gradleApi()
}
}
repositories {
jcenter()
}
複製代碼
在app 的build.gradle中,能夠這樣使用:
plugins {
id 'com.android.application'
id 'kotlin-android'
}
android {
//略
}
dependencies {
//略
//修改成直接在 afterEvaluate 後調用函數設置
// testImplementation Deps.junit
// androidTestImplementation KDeps.ext_junit
androidTestImplementation 'androidx.test.espresso:espresso-core:3.3.0'
}
afterEvaluate {
Deps.applyAll(project)
}
複製代碼
固然,咱們在這個過程當中還可使用各種編程技巧。
此時,咱們已經擁有了無限可能,根據項目的實際需求
,自行拓展吧。