【標(biāo)題黨警告】本文主要內(nèi)容為 Gradle依賴替換規(guī)則詳解坯沪。
作者:卻把清梅嗅
鏈接:https://juejin.im/post/5d2dee0851882569755f5494
來源:掘金
RxJava3版本遷移的血淚史
不久前RxJava
正式發(fā)布了3.x
版本蹲姐,作為RxJava
的愛好者提茁,筆者第一時(shí)間對(duì)個(gè)人項(xiàng)目進(jìn)行了3.x
版本的遷移阱表。
遷移過程中遇到了一個(gè)小問題殿如,那就是RxAndroid
因?yàn)闆]有及時(shí)升級(jí),因此內(nèi)部還是依賴2.x
版本的RxJava
,這就導(dǎo)致項(xiàng)目的依賴發(fā)生了沖突最爬。
筆者的解決方式非常簡單涉馁,既然RxAndroid
依賴了不合適的RxJava
版本,我就把它的依賴排除掉就可以了:
implementation ('io.reactivex.rxjava2:rxandroid:2.1.0') {
exclude group: 'io.reactivex.rxjava2', module: 'rxjava'
}
復(fù)制代碼
這樣做之后爱致,項(xiàng)目成功將RxJava
遷移到了3.x
版本烤送,筆者還第一時(shí)間在 這篇文章 中進(jìn)行了如下的評(píng)論:
評(píng)論發(fā)出去了一段時(shí)間,并沒有收到各路大神的批評(píng)糠悯,筆者便以為這就是 正確的升級(jí)方式帮坚,于是在 RxAndroid 的這個(gè) issue 中 沾沾自喜 地進(jìn)行了分享:
沒想到 JakeWharton 竟然看到了我的回復(fù),并且非常直接針對(duì)我提供的代碼進(jìn)行了點(diǎn)評(píng):
翻譯過來的意思就是:
長遠(yuǎn)來看互艾,制定一個(gè) 替換規(guī)則 遠(yuǎn)比通過
exclude
這種類似 打地鼠 的方式要好得多试和。
收到男神的回復(fù)令我受寵若驚,但我更迫切需要了解我的代碼問題出在了哪里—— 我一直認(rèn)為我的代碼就是正確的處理方案纫普,但事實(shí)卻證明了我的無知阅悍。
我翻閱了對(duì)應(yīng)的Gradle
文檔,Gradle
中提供了對(duì)應(yīng)的 依賴替換規(guī)則昨稼,而我之前一直沒有了解過它节视,這也正是本文的主要內(nèi)容。
依賴替換規(guī)則
依賴替換規(guī)則的適用場景分為以下幾種:
- 1.根據(jù)某些條件對(duì)依賴進(jìn)行替換假栓;
- 2.將本地依賴替換為外部依賴寻行;
- 3.將外部依賴替換為本地依賴;
我們先解釋一下 外部依賴 和 本地依賴 是什么匾荆。
外部依賴
外部依賴拌蜘,顧名思義,就是從遠(yuǎn)程倉庫拉取的依賴棋凳,也被稱為常用的 三方庫:
// 從遠(yuǎn)程倉庫拉取的開源代碼庫
implementation 'com.facebook.stetho:stetho:1.5.1'
implementation 'io.reactivex.rxjava3:rxjava:3.0.0-RC0'
復(fù)制代碼
本地依賴
本地依賴拦坠,也就是我們項(xiàng)目中常見的module
,按照《阿里Java開發(fā)手冊(cè)》中來描述连躏,也叫做 一方庫:
implementation project(':library')
復(fù)制代碼
好的剩岳,現(xiàn)在我們了解了這兩個(gè)基本概念,問題來了:
知道這些有什么用入热?
有同學(xué)肯定會(huì)有這個(gè)困惑拍棕,這些概念我雖然都了解了晓铆,但實(shí)際開發(fā)過程中我并沒有用到這些, 項(xiàng)目依然穩(wěn)定的迭代和運(yùn)行绰播,那學(xué)習(xí)這些東西有什么用呢骄噪?
這些規(guī)則真的很有用,在實(shí)際開發(fā)過程中蠢箩,我們肯定會(huì)遇到一些問題链蕊,這些問題我們通過baidu
或者google
的方式繞了過去,但是這真的解決了嗎谬泌?
比如說 依賴沖突滔韵。
1.根據(jù)某些條件對(duì)依賴進(jìn)行替換
舉個(gè)例子,很多UI三方庫都會(huì)依賴RecyclerView
掌实,但這么多的依賴庫陪蜻,我們不可避免遇到版本不同導(dǎo)致依賴沖突的情況,一般情況下贱鼻,我們是這么解決的:
// 將RecyclerView的依賴從這個(gè)三方庫中排除掉
implementation "xxx.xxx:xxx:1.0.0",{
exclude group: 'com.android.support', module: 'recyclerview-v7'
}
復(fù)制代碼
將RecyclerView
的依賴從這個(gè)三方庫中排除掉宴卖,令其使用項(xiàng)目本身的RecyclerView
版本,這樣項(xiàng)目就可以正常運(yùn)行了邻悬,看起來并沒有什么問題症昏。
JakeWharton 非常敏銳地點(diǎn)出了問題的所在——試想,如果項(xiàng)目的依賴比較復(fù)雜父丰,也許我們要面對(duì)的將是這樣的依賴配置:
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'
}
復(fù)制代碼
我們需要將每個(gè)依賴了RecyclerView
的三方庫都通過exclude
的方式移除掉本身對(duì)應(yīng)的依賴齿兔,這種縫縫補(bǔ)補(bǔ)式地亂堵,不正是在 打地鼠 么础米。
針對(duì)類似這種情況分苇,我們可以在gradle
的構(gòu)建過程中強(qiáng)制指定依賴的版本,以筆者的項(xiàng)目為例屁桑,我們針對(duì)RxJava
的版本依賴進(jìn)行了統(tǒng)一:
現(xiàn)在医寿,項(xiàng)目中所有RxJava
相關(guān)的依賴,在構(gòu)建過程中版本都統(tǒng)一使用了3.0.0-RC0
蘑斧,這樣就 避免了依賴沖突靖秩,開發(fā)者再也不需要針對(duì)每一個(gè)有RxJava
依賴的三方庫進(jìn)行額外的exclude
了。
2.本地依賴替換為外部依賴
本地依賴替換為外部依賴竖瘾,最經(jīng)典的場景就是SDK
的發(fā)布測試沟突,如果您有過開源項(xiàng)目的經(jīng)歷,對(duì)此一定不會(huì)陌生捕传。
以筆者開源的 RxImagePicker 為例惠拭,日常開發(fā)過程中,sample
代碼依賴本地的module
;新版本發(fā)布后职辅,筆者的UI測試代碼便需要通過依賴jcenter
遠(yuǎn)程倉庫的最新代碼棒呛。
這種情況下,通過dependencySubstitution
便可以非常方便對(duì)這兩種場景進(jìn)行切換:
useRemote
只是定義在build.gradle
文件中的一個(gè)變量域携,作為切換開發(fā)-測試環(huán)境的開關(guān):
final boolean useRemote = true
復(fù)制代碼
當(dāng)useRemote
值為true
時(shí)簇秒,sample
依賴遠(yuǎn)程倉庫,當(dāng)值為false
時(shí)秀鞭,sample
依賴本地module
趋观。
看起來代碼量反而增加了,實(shí)際上锋边,隨著項(xiàng)目復(fù)雜度的提升拆内,這種全局的配置優(yōu)點(diǎn)顯而易見。
3.將外部依賴替換為本地依賴
該規(guī)則和2非常相似宠默,只不過將依賴替換的雙方調(diào)換了而已麸恍,下面是官方的示例代碼:
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")
}
}
復(fù)制代碼
最終的遷移方案?
故事的最后搀矫,筆者的解決方案如下:
- 1.因?yàn)?code>group不同抹沪,所以需要先將
2.x
的rxjava
全局exclude
掉; - 2.將所有
3.x
的rxjava
的依賴版本都統(tǒng)一(文中是3.0.0-RC0
)瓤球;
筆者并不知道這種方式是否就是 JakeWharton 描述的解決方案融欧,但相比較之前而言效果確實(shí)更好,如果有更好的依賴管理方案卦羡,誠摯希望您能在評(píng)論區(qū)中進(jìn)行分享噪馏。
感受
GitHub
確實(shí)是一個(gè)神奇的東西,它讓我避免固步自封绿饵,畢竟世界上最頂尖的開發(fā)者們都聚焦于此欠肾,在他們眼里,你的代碼永遠(yuǎn)都有著非常廣闊的進(jìn)步空間拟赊。
發(fā)現(xiàn)自己的短板不是壞事刺桃,它可以督促我不斷去嘗試自我超越,就像我常年放在文章末尾的那句話一樣吸祟,萬一哪天我進(jìn)步了呢瑟慈?