Error while generating the main dex list
今天編譯專案,編譯報錯。
FAILURE: Build failed with an exception.
* What went wrong:
Execution failed for task ':app:transformClassesWithMultidexlistForInstant_runDebug'.
> com.android.build.api.transform.TransformException: Error while generating the main dex list.
習慣上直接 copy 錯誤 ,在 stackoverflow 上查詢答案。
花了十幾分鍾仍然沒找到答案。
直接在 Android Studio 中的命令列中執行。
gradle assembleDebug --stacktrace
發現了以下錯誤 :
Caused by: com.android.tools.r8.errors.CompilationError: Program type already present: okhttp3.Authenticator$1
原因很簡單 jar 包衝突了 。
我使用了一個第三方庫,第三方庫依賴了 OkHttp 。 而我專案中原本就有 OkHttp 。
compile ("com.facebook.react:react-native:0.55.4")
找到問題的原因後,解決就很快了。直接移除第三方庫所依賴的 OkHttp 即可。
compile ("com.facebook.react:react-native:0.55.4") {
exclude group: 'com.squareup.okhttp3'
}
如果你也遇到了這樣的報錯 , 可能是 jar 包衝突 。
通常這樣的問題是在 Gradle 中新新增的依賴第三方庫引起的。
如何來排查複雜些的問題呢 ?
Android 專案中大部分通過 Gradle 遠端依賴, 建議通過檢視依賴樹來排查問題 :
例如我的 Android 工程主 Module 名稱為 app 。我想檢視依賴樹,進入專案根目錄,執行命令:
gradlew app:dependencies
Terminal 中會打印出很多文字 , 如 :
其中 recyclerview 是我在 build.gradle 中直接依賴的。
implementation 'com.android.support:recyclerview-v7:26.1.0
而下面三行程式碼是 recyclerview 所依賴的庫。
| +--- com.android.support:support-annotations:26.1.0 (*)
| +--- com.android.support:support-compat:26.1.0 (*)
| \--- com.android.support:support-core-ui:26.1.0 (*)
因此大多數情況下的衝突是因為,依賴庫所依賴的其他庫版本衝突。
想要處理這種問題,我給大家介紹幾種方法。
exclude
exclude : 剔除依賴 。還給大家舉上面的例子。
recyclerview 不想要依賴 com.android.support:support-annotations:26.1.0 怎麼辦 ?
有辦法 :
implementation ('com.android.support:recyclerview-v7:26.1.0'){
exclude group: 'com.android.support', module: 'support-annotations' // 根據組織名 + 構建名剔除
// 你也可以分別通過 group 和 module 剔除 對應的模組。
}
執行後的依賴樹如下 :
+--- com.android.support:recyclerview-v7:26.1.0
| +--- com.android.support:support-compat:26.1.0 (*)
| \--- com.android.support:support-core-ui:26.1.0 (*)
force
force : 強制指定依賴版本。
例如,我想要所有 com.android.support:support-annotations:26.1.0 的依賴版本為 27.1.1 怎麼辦呢 ?
在只需要在 build.gradle 中加上 force true 即可 :
implementation("com.android.support:support-annotations:27.1.1"){
force true
}
執行後檢視依賴樹的結果 :
+--- com.android.support:recyclerview-v7:26.1.0
| +--- com.android.support:support-annotations:26.1.0 -> 27.1.1
| +--- com.android.support:support-compat:26.1.0 (*)
| \--- com.android.support:support-core-ui:26.1.0 (*)
大家看到多了 -> 27.1.1 . 也就是原依賴版本為 26.1.0 ,在工程中修改依賴為 27.1.1 。
transitive
transitive : 依賴傳遞特性,使用的時候,通常設定為 false 。即關閉依賴傳遞
例如專案中不希望 recyclerview 使用它所依賴的庫 :
| +--- com.android.support:support-annotations:26.1.0 (*)
| +--- com.android.support:support-compat:26.1.0 (*)
| \--- com.android.support:support-core-ui:26.1.0 (*)
在只需要在 build.gradle 中加上 transitive false 即可 :
implementation ('com.android.support:recyclerview-v7:26.1.0'){
transitive false
}
執行後檢視依賴樹的結果 , recyclerview 的依賴都消失了。當然這是一個危險的操作,因為
缺少依賴,你可能無法正常編譯。最好確認你專案中已經依賴了你所剔除在外的庫。
+--- com.android.support:recyclerview-v7:26.1.0
上述操作等同於 :
implementation('com.android.support:recyclerview-v7:26.1.0') {
exclude group : 'com.android.support'
}
因為 recyclerview 依賴的三個庫組織名都是 com.android.support
總結
解決衝突用的最多是 force 和 exclude 。
本來這麼簡單一個問題,應該在1分鐘內解決的。卻前前後後花了 十幾分鍾。
發現自己太依賴 Google 了。
首先應該是鍛鍊自己排查問題的能力,然後再面向 Github 程式設計 和 面向 stackoverflow 程式設計。