Gradle 使用技巧(四) - 如何定位和解決依賴衝突

傲寒遙發表於2018-08-25

1. 前言

隨著業務的複雜度加深,我們免不了要引入許多的第三方開源庫,也不可避免的會出現依賴衝突的錯誤。最常見的是V7、V4包之間的衝突。

2. 如何定位依賴衝突

解決依賴衝突很簡單,難得是如何去定位是引入的哪個庫導致的依賴衝突。 如果只想看結果的可以直接跳到最後。

2.1. 排除法

排除法很簡單,但是很耗時,就是選擇一個依賴一個依賴的註釋、編譯、看結果。當然這也是最傻的辦法,我們開發者怎麼能做這種繁瑣的工作呢?(說得我好像我自己沒做過似的。。

滑稽
)

2.2. Gradle Task

Android Studio雖然給我們提供了一個依賴樹,但也只是一個總的平面圖,並不是十分的直觀。

Android Studio依賴樹

External Libraries只給我們提供了一個依賴結果,並沒有指出是哪個依賴依賴了什麼東西。

所幸,Gradle提供了一個task:androidDependencies,這個task能在命令列中顯示依賴樹之間的依賴關係。

找到androidDependencies task,每一個module下面都有相應的androidDependencies。

task位置

雙擊執行後就能在命令列中列印相關的依賴資訊了,這裡為了演示,我新建了一個專案。

命令列執行結果

如上圖,可以看到不同的buildType的所有資訊都列印出來了,比如release:

release
releaseCompileClasspath - Dependencies for compilation
+--- com.android.support:appcompat-v7:26.1.0@aar
+--- com.android.support.constraint:constraint-layout:1.1.2@aar
+--- com.android.support:animated-vector-drawable:26.1.0@aar
+--- com.android.support:support-vector-drawable:26.1.0@aar
+--- com.android.support:support-v4:26.1.0@aar
+--- com.android.support:support-media-compat:26.1.0@aar
+--- com.android.support:support-fragment:26.1.0@aar
+--- com.android.support:support-core-utils:26.1.0@aar
+--- com.android.support:support-core-ui:26.1.0@aar
+--- com.android.support:support-compat:26.1.0@aar
+--- com.android.support:support-annotations:26.1.0@jar
+--- com.android.support.constraint:constraint-layout-solver:1.1.2@jar
+--- android.arch.lifecycle:runtime:1.0.0@aar
+--- android.arch.lifecycle:common:1.0.0@jar
\--- android.arch.core:common:1.0.0@jar
複製程式碼

當然,這只是一個剛剛新增的專案,資訊才這麼少,如果是維護很久了的專案,那麼資訊將會讓人眼花。

我們可以改為用命令列的方式列印資訊,還可以進行相關的配置,配置的方法為:-q --configuration 依賴型別,如下就是列印implementation型別的依賴

./gradlew app:dependencies -q --configuration implementation
複製程式碼

可以看到,結果明顯精簡了很多

執行結果

但是,我們仍然看不出什麼東西是吧?所以,請看下一步

2.3. 引入外掛

前面說了,作為一個開發者,怎麼能做那麼多繁瑣的事情呢?所以這裡有個插(wu)件(qi)

可以直接通過皮膚的形式看到是哪個依賴庫,具體是衝突了哪個版本。

外掛截圖

該外掛的適應方式比較簡單,就不多講了。

3. 如何解決衝突

3.1. jar包衝突

這是最簡單的,刪除其中一個jar包。

3.2. 在明確的知道是哪個庫的哪些依賴的情況下

可以使用exclude來去除傳遞依賴,如下:

3.2.1 exclude group

根據包名來過濾,下面的配置是:過濾包名"com.android.support"的所有依賴

androidTestCompile('com.android.support.test.espresso:espresso-core:2.2.2', {
        exclude group: 'com.android.support'
    })
複製程式碼

3.2.2 exclude module

根據模組名稱來過濾下面的配置是過濾"support-annotations"這個模組

androidTestCompile('com.android.support.test.espresso:espresso-core:2.2.2', {
        exclude module: 'support-annotations'
    })
複製程式碼

3.3. 不知道是哪個庫的傳遞依賴導致衝突

這種情況最常見,我不想去找,也不想去逐個排除,那麼就有以下兩種方案:

3.3.1 一勞永逸法

直接統一指定transitive,就是為給dependencies配置transitive為false,這樣就會以你當前依賴的版本為準。但是最好不要使用這種方式。

...
configurations.all {
   transitive = false
}
...
dependencies{
}
複製程式碼

需要注意的是configurations和android、dependencies節點是處於同一級的。

3.3.2 逐個指定

哪個衝突指定哪個。具體可以檢視我另外一篇文章Gradle之強制依賴某個第三方庫

configurations.all {
    resolutionStrategy.force "com.android.support:appcompat-v7:22.2.1"
}
複製程式碼

指定依賴

最後

未完待續、敬請期待! 免為其難的關注一下公眾號吧!!

生活實在是太苦啦

FullScreenDeveloper

相關文章