查看依賴(lài)庫(kù)和隱含依賴(lài)導(dǎo)致的問(wèn)題

Android Studio使用gradle來(lái)管理項(xiàng)目,使用依賴(lài)庫(kù)也很簡(jiǎn)單,在build.gradle中配置一下就可以了。但是這么方便的工具也隱含很多坑,隱含依賴(lài)問(wèn)題就是其中之一。

例如如果同一個(gè)jar包卻有兩個(gè)版本,導(dǎo)致ClassLoader加載出錯(cuò),或者干脆生成dex的時(shí)候就報(bào)錯(cuò),讓你編譯都不過(guò)。就是說(shuō)這類(lèi)錯(cuò)誤可能發(fā)生在編譯期,也可能發(fā)生在運(yùn)行期(例如加載多個(gè)dex)。錯(cuò)誤提示也是多種多樣。

查看依賴(lài)庫(kù)的命令行工具

$gradle <host_module_name>:dependencies 可以看到指定module的所有的間接依賴(lài)庫(kù),也就是依賴(lài)庫(kù)的依賴(lài)庫(kù)

$gradle showAllCache 可以看到所在module的所有依賴(lài)庫(kù)的路徑

前提是在module的build.gradle中加入showAllCache的task,如下

task showAllCache << {
   configurations.compile.each { println it }
}

遇到版本依賴(lài)問(wèn)題總是很煩,需要仔細(xì)看log,有了查看依賴(lài)的方法就能省很多時(shí)間。

怎么定位是依賴(lài)庫(kù)的問(wèn)題?

錯(cuò)誤提示多種多樣,沒(méi)有統(tǒng)一的log。如果是沒(méi)見(jiàn)過(guò)的錯(cuò)誤,可以google一下,一般都會(huì)有人遇到,然后說(shuō)這是依賴(lài)庫(kù)的版本沖突或干脆就說(shuō)是依賴(lài)庫(kù)的問(wèn)題,但是也就到這里為止了(可能因?yàn)殄e(cuò)誤一般都是自己項(xiàng)目特有的,不好寫(xiě)總結(jié))。

下邊舉兩個(gè)例子,都是我遇到的。

錯(cuò)誤舉例

1 隱含依賴(lài)導(dǎo)致混淆出錯(cuò) :app:transformClassesWithMultidexlistForDebug

在打包過(guò)程中報(bào)錯(cuò),詳細(xì)的log見(jiàn)我在stackoverflow上的問(wèn)題

看log里有提示

“Error:Uncaught translation error: com.android.dex.util.ExceptionWithContext: name already added: string{"a"}”

這是我在注音輸入法里遇到的,build.gradle中加上使用

minifyEnabled = false

打包成功;

minifyEnabled = true

打包失敗。很顯然跟混淆有關(guān)。

問(wèn)題是怎么定位到具體是哪個(gè)庫(kù)沒(méi)做混淆或者不應(yīng)該混淆呢?
build.gradle中用到的所有庫(kù)我都在proguard中加了keep,為啥還有問(wèn)題?

我當(dāng)時(shí)用了笨辦法,一個(gè)個(gè)排除。結(jié)果花了很長(zhǎng)時(shí)間才找到出問(wèn)題的依賴(lài)庫(kù)。根本原因就是com.squareup.retrofit2依賴(lài)fastxml,后者沒(méi)在proguard中被keep。

后來(lái)在網(wǎng)上找到上邊查看間接依賴(lài)的方法,試了一下,果然很好使。早知道這個(gè)方法的話我就能省很多時(shí)間了:-(

2 隱含依賴(lài)導(dǎo)致版本沖突
W/art: Incompatible structural change detected: Structural change of android.support.v4.app.FragmentActivity is hazardous (/data/user/0/<package_name>/files/dexOpt/com.tugele.expression.odex/plugin_doutu-debug.dex at compile time, /data/app/<package_name>-1/oat/arm/base.odex at runtime): Virtual method count off: 45 vs 46
W/art: Landroid/support/v4/app/FragmentActivity; (Compile time):

這個(gè)錯(cuò)誤是在通過(guò)輸入法啟動(dòng)圖個(gè)樂(lè)插件(單獨(dú)的apk包)時(shí)發(fā)生的。排除各種錯(cuò)誤后把問(wèn)題定位到android.support.v4的版本上,host和plugin使用了不同版本的support-v4版本上。

分析過(guò)程

第一步:驗(yàn)證一下錯(cuò)誤原因是否屬實(shí)。分別把host(主工程)和plugin(插件)的dex反編譯成jar,然后用jd-gui查看FragmentActivity.class,發(fā)現(xiàn)確實(shí)不一樣。

那問(wèn)題就來(lái)了,host和plugin中指定的android-support-v4.jar的版本是一樣的,build.gradle中寫(xiě)的都是“compile 'com.android.support:support-v4:23.1.1'”,版本一樣為啥看到的代碼不一樣呢?

第二步:驗(yàn)證一下項(xiàng)目實(shí)際依賴(lài)的庫(kù)。

怎么驗(yàn)證?

到host和plugin目錄下,分別在命令行下執(zhí)行 $gradle
host的依賴(lài)輸出:

...................
<SDK_PATH>/extras/android/m2repository/com/android/support/support-v4/23.2.1/support-v4-23.2.1.aar
....................

plugin的依賴(lài)輸出:

...................
<SDK_PATH>/extras/android/m2repository/com/android/support/support-v4/23.1.1/support-v4-23.1.1.aar
....................

發(fā)現(xiàn)問(wèn)題木有?
host和plugin實(shí)際依賴(lài)的版本不一樣!??!

為什么會(huì)這樣?host為什么不用指定的版本23.1.1 ?

原因就是其它依賴(lài)庫(kù)間接的依賴(lài)android-support-v4-23.2.1。那么是誰(shuí)間接依賴(lài)它呢?

要查明原因就要用這個(gè)命令:$gradle <host_module_name>:dependencies
它能把所有庫(kù)的依賴(lài)關(guān)系都展示給你。

看我的結(jié)果:

+--- project :zhushou_sdk
| +--- com.android.support:recyclerview-v7:23.2.1
| | +--- com.android.support:support-v4:23.2.1 (*)
| | --- com.android.support:support-annotations:23.2.1

看到了嗎?com.android.support:recyclerview間接依賴(lài)到com.android.support:support-v4:23.2.1

再多看一點(diǎn):

+--- project :explore_base_module
| --- com.android.support:support-v4:23.1.1 -> 23.2.1 (*)

這個(gè)module本來(lái)是依賴(lài)23.1.1的,gradle要照顧到版本兼容問(wèn)題,所以就該成了23.2.1

這就是問(wèn)題的根本原因。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書(shū)系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

推薦閱讀更多精彩內(nèi)容

  • Android 自定義View的各種姿勢(shì)1 Activity的顯示之ViewRootImpl詳解 Activity...
    passiontim閱讀 173,116評(píng)論 25 708
  • Spring Cloud為開(kāi)發(fā)人員提供了快速構(gòu)建分布式系統(tǒng)中一些常見(jiàn)模式的工具(例如配置管理,服務(wù)發(fā)現(xiàn),斷路器,智...
    卡卡羅2017閱讀 134,881評(píng)論 18 139
  • afinalAfinal是一個(gè)android的ioc,orm框架 https://github.com/yangf...
    passiontim閱讀 15,492評(píng)論 2 45
  • 意洞君: 昨日倚窗,門(mén)廊傳來(lái)腳步聲,聽(tīng)四娘呼,覺(jué)民回來(lái)了。君一邊應(yīng)四娘,一邊快步奔來(lái)。妾匆匆開(kāi)門(mén),不見(jiàn)意洞,怔。停...
    李麗霞閱讀 422評(píng)論 2 3