Android Gradle 隱形依賴的奇怪案例

相信 Android 開發者都有在 Android Studio 中升級 compileSdkVersion 的經歷,這個時候若是你使用了 support 包,並同時升級,那麼可能會出現一個錯誤提示。本文教你如何解決這個問題。
在 Android Studio 中,Gradle 構建過程大多數都是抽象的。做爲一個新手 Android 開發者,咱們在使用 Gradle 的時候首先遇到的問題一般都是如何在 build.gradle 中添加遠程依賴。android

讓咱們來看一個情形並學習如何查看依賴樹,以及解決依賴相關的問題。app

我正在開發一個項目,而且我想把構建版本提高到最新的 API 27。同時,我把 build.gradle 中的 appcompat-v7 擴展庫也升級到了 27.0.2.而後我 sync 項目,出現了以下錯誤:學習

全部的 com.android.support 庫都必須使用相同的版本gradle

這個錯誤說我必須使用徹底相同版本的擴展包。很直接,可是個人 build.gradle 中只有這一個擴展包。Android Studio 在說什麼呢? 😕上面提到的 com.android.support:animated-vector-drawable:27.0.2 和 com.android.support-v4:21.0.3 到底在哪?ui

若是隻有 build.gradle 中的依賴那麼事情會變得很簡單,但事實並不是如此。這些依賴可能有一些別的依賴,別的依賴中又有另外一些依賴等等等等。這就叫傳遞依賴,Gradle 須要把全部的這些直接/間接的依賴打包到 app 當中。Android Studio 的錯誤提示就是在說這些傳遞依賴。spa

Gradle 必定有某種方式來解決全部的依賴。哪一個庫要添加?若是兩個不一樣的庫都依賴於相同的庫的不一樣版本呢?咱們來深刻了解一下發生了什麼。ci

要查看依賴樹(Gradle 解決依賴的方式),咱們能夠打開 Android Studio 的終端,而後輸入如下命令(Windows):開發

gradlew app:dependencies
mac:get

./gradlew app:dependencies
這會展現全部構建變體的依賴樹。咱們能夠在上面的命令中添加一個標識來查看特定變體的配置。好比: --configuration releaseCompileClasspath 將會展現 release 變體的依賴樹。io

上面命令的輸出是這樣的:

releaseCompileClasspath - Resolved configuration for compilation for variant: release
+--- com.android.databinding:library:1.3.1
| +--- com.android.support:support-v4:21.0.3
| | --- com.android.support:support-annotations:21.0.3 -> 27.0.2
| --- com.android.databinding:baseLibrary:2.3.0-dev -> 3.0.1
+--- com.android.databinding:baseLibrary:3.0.1
+--- com.android.databinding:adapters:1.3.1
| +--- com.android.databinding:library:1.3 -> 1.3.1 ()
| --- com.android.databinding:baseLibrary:2.3.0-dev -> 3.0.1
+--- com.android.support.constraint:constraint-layout:1.0.2
| --- com.android.support.constraint:constraint-layout-solver:1.0.2
--- com.android.support:appcompat-v7:27.0.2
+--- com.android.support:support-annotations:27.0.2
+--- com.android.support:support-core-utils:27.0.2
| +--- com.android.support:support-annotations:27.0.2
| --- com.android.support:support-compat:27.0.2
| +--- com.android.support:support-annotations:27.0.2
| --- android.arch.lifecycle:runtime:1.0.3
| +--- android.arch.lifecycle:common:1.0.3
| --- android.arch.core:common:1.0.0
+--- com.android.support:support-fragment:27.0.2
| +--- com.android.support:support-compat:27.0.2 (
)
| +--- com.android.support:support-core-ui:27.0.2
| | +--- com.android.support:support-annotations:27.0.2
| | --- com.android.support:support-compat:27.0.2 ()
| +--- com.android.support:support-core-utils:27.0.2 (
)
| --- com.android.support:support-annotations:27.0.2
+--- com.android.support:support-vector-drawable:27.0.2
| +--- com.android.support:support-annotations:27.0.2
| --- com.android.support:support-compat:27.0.2 ()
--- com.android.support:animated-vector-drawable:27.0.2
+--- com.android.support:support-vector-drawable:27.0.2 (
)
--- com.android.support:support-core-ui:27.0.2 (*)
在查看問題以前理解依賴樹的格式是很是重要的。先來看看下面的三個符號,它們只是用來格式化的:

  • --- 是一個庫分支的開始

| 表示繼續顯示這個庫所依賴的分支

--- 表示分支的結束

(*) 在一個庫的後面表示這個庫的更多依賴沒有顯示,由於它們已經在其餘子樹中列出來了。

最重要的符號是 ->

在 Gradle 中若是多個庫依賴於相同的庫的不一樣版本,那麼它會作出選擇。包含庫的不一樣版本是不合理的。所以,Gradle 默認選擇那個庫的最新版本。

| + — — com.android.support:support-v4:21.0.3
| | \ — — com.android.support:support-annotations:21.0.3 -> 27.0.2
上面顯示的是儘管 support-v4:21.0.3 依賴於 support-annotations:21.0.3 ,可是有一個新版本 support-annotations:27.0.2 在依賴樹中,因此 27.0.2 將會被使用。

https://pic3.zhimg.com/80/v2-...

如今咱們知道如何查看 Gradle 依賴樹了,回到剛纔的問題:全部的 com.android.support 庫都必須使用徹底相同的版本。

全部的擴展包都在 com.android.support 組中,咱們在上面的依賴樹中能夠看到 com.android.support:support-v4:21.0.3 只是 21.0.3 版本的,沒有使用最新的 27.0.2 版本。這裏致使了衝突。

怎麼解決這個問題呢?有幾種方式:

實現一個解決策略,讓 Gradle 強制使用某個版本:
android {
configurations.all {
// To resolve the conflict for com.android.databinding:library:1.3.1
// dependency on support-v4:21.0.3
resolutionStrategy.force 'com.android.support:support-v4:27.0.2'
}
}
在 build.gradle 中顯式添加 com.android.support:support-v4:27.0.2 ,這樣 Gradle 就會覆蓋以前的舊版本。
dependencies {
implementation fileTree(dir: 'libs', include: ['*.jar'])
implementation 'com.android.support.constraint:constraint-layout:1.0.2'
// To resolve the conflict for com.android.databinding:library:1.3.1
// dependency on support-v4:21.0.3
implementation 'com.android.support:support-v4:27.0.2'
implementation 'com.android.support:appcompat-v7:27.0.2'
}
對於我來講,顯式添加依賴看起來更加天然。在 build.gradle 中的註釋會提醒咱們再次更新時是否須要顯式地添加這個依賴。

添加依賴後,再次 sync,錯誤提示就會消失了,如今咱們再次運行命令會看到 support-v4:21.0.3 被標記爲 -> 27.0.2 了。

https://pic3.zhimg.com/80/v2-...

原文連接:Android Gradle and the curious case of invisible dependency

相關文章
相關標籤/搜索