【標題黨警告】本文主要內容爲 Gradle依賴替換規則詳解。java
不久前RxJava
正式發佈了3.x
版本,做爲RxJava
的愛好者,筆者第一時間對我的項目進行了3.x
版本的遷移。react
遷移過程當中遇到了一個小問題,那就是RxAndroid
由於沒有及時升級,所以內部仍是依賴2.x
版本的RxJava
,這就致使項目的依賴發生了衝突。android
筆者的解決方式很是簡單,既然RxAndroid
依賴了不合適的RxJava
版本,我就把它的依賴排除掉就能夠了:git
implementation ('io.reactivex.rxjava2:rxandroid:2.1.0') {
exclude group: 'io.reactivex.rxjava2', module: 'rxjava'
}
複製代碼
這樣作以後,項目成功將RxJava
遷移到了3.x
版本,筆者還第一時間在 這篇文章 中進行了以下的評論:github
評論發出去了一段時間,並無收到各路大神的批評,筆者便覺得這就是 正確的升級方式,因而在 RxAndroid 的這個 issue 中 沾沾自喜 地進行了分享:api
沒想到 JakeWharton 居然看到了個人回覆,而且很是直接針對我提供的代碼進行了點評:app
翻譯過來的意思就是:post
長遠來看,制定一個 替換規則 遠比經過
exclude
這種相似 打地鼠 的方式要好得多。學習
收到男神的回覆令我受寵若驚,但我更迫切須要瞭解個人代碼問題出在了哪裏—— 我一直認爲個人代碼就是正確的處理方案,但事實卻證實了個人無知。測試
我翻閱了對應的Gradle
文檔,Gradle
中提供了對應的 依賴替換規則,而我以前一直沒有了解過它,這也正是本文的主要內容。
依賴替換規則的適用場景分爲如下幾種:
咱們先解釋一下 外部依賴 和 本地依賴 是什麼。
外部依賴,顧名思義,就是從遠程倉庫拉取的依賴,也被稱爲經常使用的 三方庫:
// 從遠程倉庫拉取的開源代碼庫
implementation 'com.facebook.stetho:stetho:1.5.1'
implementation 'io.reactivex.rxjava3:rxjava:3.0.0-RC0'
複製代碼
本地依賴,也就是咱們項目中常見的module
,按照**《阿里Java開發手冊》**中來描述,也叫作 一方庫:
implementation project(':library')
複製代碼
好的,如今咱們瞭解了這兩個基本概念,問題來了:
有同窗確定會有這個困惑,這些概念我雖然都瞭解了,但實際開發過程當中我並無用到這些, 項目依然穩定的迭代和運行,那學習這些東西有什麼用呢?
這些規則真的頗有用,在實際開發過程當中,咱們確定會遇到一些問題,這些問題咱們經過baidu
或者google
的方式繞了過去,可是這真的解決了嗎?
好比說 依賴衝突。
舉個例子,不少UI三方庫都會依賴RecyclerView
,但這麼多的依賴庫,咱們不可避免遇到版本不一樣致使依賴衝突的狀況,通常狀況下,咱們是這麼解決的:
// 將RecyclerView的依賴從這個三方庫中排除掉
implementation "xxx.xxx:xxx:1.0.0",{
exclude group: 'com.android.support', module: 'recyclerview-v7'
}
複製代碼
將RecyclerView
的依賴從這個三方庫中排除掉,令其使用項目自己的RecyclerView
版本,這樣項目就能夠正常運行了,看起來並無什麼問題。
JakeWharton 很是敏銳地點出了問題的所在——試想,若是項目的依賴比較複雜,也許咱們要面對的將是這樣的依賴配置:
implementation "libraryA:xxx:1.0.0",{
exclude group: 'com.android.support', module: 'recyclerview-v7'
}
implementation "libraryB:xxx:2.2.0",{
exclude group: 'com.android.support', module: 'recyclerview-v7'
}
implementation "libraryC:xxx:0.0.8",{
exclude group: 'com.android.support', module: 'recyclerview-v7'
}
複製代碼
咱們須要將每一個依賴了RecyclerView
的三方庫都經過exclude
的方式移除掉自己對應的依賴,這種縫縫補補式地亂堵,不正是在 打地鼠 麼。
針對相似這種狀況,咱們能夠在gradle
的構建過程當中強制指定依賴的版本,以筆者的項目爲例,咱們針對RxJava
的版本依賴進行了統一:
如今,項目中全部RxJava
相關的依賴,在構建過程當中版本都統一使用了3.0.0-RC0
,這樣就 避免了依賴衝突,開發者不再須要針對每個有RxJava
依賴的三方庫進行額外的exclude
了。
本地依賴替換爲外部依賴,最經典的場景就是SDK
的發佈測試,若是您有過開源項目的經歷,對此必定不會陌生。
以筆者開源的 RxImagePicker 爲例,平常開發過程當中,sample
代碼依賴本地的module
;新版本發佈後,筆者的UI測試代碼便須要經過依賴jcenter
遠程倉庫的最新代碼。
這種狀況下,經過dependencySubstitution
即可以很是方便對這兩種場景進行切換:
useRemote
只是定義在build.gradle
文件中的一個變量,做爲切換開發-測試環境的開關:
final boolean useRemote = true
複製代碼
當useRemote
值爲true
時,sample
依賴遠程倉庫,當值爲false
時,sample
依賴本地module
。
看起來代碼量反而增長了,實際上,隨着項目複雜度的提高,這種全局的配置優勢顯而易見。
該規則和2很是類似,只不過將依賴替換的雙方調換了而已,下面是官方的示例代碼:
configurations.all {
resolutionStrategy.dependencySubstitution {
substitute module("org.utils:api") because "we work with the unreleased development version" with project(":api")
substitute module("org.utils:util:2.5") with project(":util")
}
}
複製代碼
故事的最後,筆者的解決方案以下:
group
不一樣,因此須要先將2.x
的rxjava
全局exclude
掉;3.x
的rxjava
的依賴版本都統一(文中是3.0.0-RC0
);筆者並不知道這種方式是否就是 JakeWharton 描述的解決方案,但相比較以前而言效果確實更好,若是有更好的依賴管理方案,誠摯但願您能在評論區中進行分享。
GitHub
確實是一個神奇的東西,它讓我避免固步自封,畢竟世界上最頂尖的開發者們都聚焦於此,在他們眼裏,你的代碼永遠都有着很是廣闊的進步空間。
發現本身的短板不是壞事,它能夠督促我不斷去嘗試自我超越,就像我常年放在文章末尾的那句話同樣,萬一哪天我進步了呢?
Hello,我是卻把清梅嗅,若是您以爲文章對您有價值,歡迎 ❤️,也歡迎關注個人我的博客或者Github。
若是您以爲文章還差了那麼點東西,也請經過關注督促我寫出更好的文章——萬一哪天我進步了呢?