JakeWharton評價個人代碼像是在打地鼠?

【標題黨警告】本文主要內容爲 Gradle依賴替換規則詳解java

RxJava3版本遷移的血淚史

不久前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中提供了對應的 依賴替換規則,而我以前一直沒有了解過它,這也正是本文的主要內容。

依賴替換規則

依賴替換規則的適用場景分爲如下幾種:

  • 1.根據某些條件對依賴進行替換;
  • 2.將本地依賴替換爲外部依賴;
  • 3.將外部依賴替換爲本地依賴;

咱們先解釋一下 外部依賴本地依賴 是什麼。

外部依賴

外部依賴,顧名思義,就是從遠程倉庫拉取的依賴,也被稱爲經常使用的 三方庫

// 從遠程倉庫拉取的開源代碼庫
implementation 'com.facebook.stetho:stetho:1.5.1'
implementation 'io.reactivex.rxjava3:rxjava:3.0.0-RC0'
複製代碼

本地依賴

本地依賴,也就是咱們項目中常見的module,按照**《阿里Java開發手冊》**中來描述,也叫作 一方庫

implementation project(':library')
複製代碼

好的,如今咱們瞭解了這兩個基本概念,問題來了:

知道這些有什麼用?

有同窗確定會有這個困惑,這些概念我雖然都瞭解了,但實際開發過程當中我並無用到這些, 項目依然穩定的迭代和運行,那學習這些東西有什麼用呢?

這些規則真的頗有用,在實際開發過程當中,咱們確定會遇到一些問題,這些問題咱們經過baidu或者google的方式繞了過去,可是這真的解決了嗎?

好比說 依賴衝突

1.根據某些條件對依賴進行替換

舉個例子,不少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了。

2.本地依賴替換爲外部依賴

本地依賴替換爲外部依賴,最經典的場景就是SDK的發佈測試,若是您有過開源項目的經歷,對此必定不會陌生。

以筆者開源的 RxImagePicker 爲例,平常開發過程當中,sample代碼依賴本地的module;新版本發佈後,筆者的UI測試代碼便須要經過依賴jcenter遠程倉庫的最新代碼。

這種狀況下,經過dependencySubstitution即可以很是方便對這兩種場景進行切換:

useRemote只是定義在build.gradle文件中的一個變量,做爲切換開發-測試環境的開關:

final boolean useRemote = true  
複製代碼

useRemote值爲true時,sample依賴遠程倉庫,當值爲false時,sample依賴本地module

看起來代碼量反而增長了,實際上,隨着項目複雜度的提高,這種全局的配置優勢顯而易見。

3.將外部依賴替換爲本地依賴

該規則和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")
    }
}
複製代碼

最終的遷移方案?

故事的最後,筆者的解決方案以下:

  • 1.由於group不一樣,因此須要先將2.xrxjava全局exclude掉;
  • 2.將全部3.xrxjava的依賴版本都統一(文中是3.0.0-RC0);

筆者並不知道這種方式是否就是 JakeWharton 描述的解決方案,但相比較以前而言效果確實更好,若是有更好的依賴管理方案,誠摯但願您能在評論區中進行分享。

感覺

GitHub確實是一個神奇的東西,它讓我避免固步自封,畢竟世界上最頂尖的開發者們都聚焦於此,在他們眼裏,你的代碼永遠都有着很是廣闊的進步空間。

發現本身的短板不是壞事,它能夠督促我不斷去嘗試自我超越,就像我常年放在文章末尾的那句話同樣,萬一哪天我進步了呢?

關於我

Hello,我是卻把清梅嗅,若是您以爲文章對您有價值,歡迎 ❤️,也歡迎關注個人我的博客或者Github

若是您以爲文章還差了那麼點東西,也請經過關注督促我寫出更好的文章——萬一哪天我進步了呢?

相關文章
相關標籤/搜索