DEX 方法超過64K限制和gradle編譯OOM問題解決

如果你是一個android開發者,你至少聽說過的Dalvik的蛋疼的64K方法限制。概括地說,在一個DEX文件,你可以調用很多的方法,但你只能調用它們最前面的65,536個 ,因爲這是在方法調用集合中的所有的空間了。如果你的源代碼和狂拽炫酷叼炸天的三方庫中方法超過了這個限制。看這篇文章就對了。

UNEXPECTED TOP-LEVEL EXCEPTION: com.android.dex.DexIndexOverflowException: method ID not in [0, 0xffff]: 65536 at com.android.dx.merge.DexMerger$6.updateIndex(DexMerger.Java:502) at com.android.dx.merge.DexMerger$IdMerger.mergeSorted(DexMerger.java:277) at com.android.dx.merge.DexMerger.mergeMethodIds(DexMerger.java:491) at com.android.dx.merge.DexMerger.mergeDexes(DexMerger.java:168) at com.android.dx.merge.DexMerger.merge(DexMerger.java:189) at com.android.dx.command.dexer.Main.mergeLibraryDexBuffers(Main.java:454) at com.android.dx.command.dexer.Main.runMonoDex(Main.java:302) at com.android.dx.command.dexer.Main.run(Main.java:245) at com.android.dx.command.dexer.Main.main(Main.java:214) at com.android.dx.command.Main.main(Main.java:106)

點此查看更多相關話題

爲了解決這個問題,Android開發社區有人想出了一些解決方案,比如dmarcato的這個,還有casidiablo的這個。他們都是可行的,但是需要一些比較嚴格的條件。

最終,Google決定提供一套官方的解決方案,在10月14日的時候發佈了MultiDex 支持庫,隨後幾周gradle在 v0.14.0版本中也支持了。

使用MultiDex支持庫

如果你在使用 Android Studio,這個用起來很簡單。如果不是,強烈建議你遷移過來。因爲Google很快就會不知處Eclipse插件和舊的基於Ant的系統構建方式。

第1步 
添加依賴於你的build.gradle支持MultiDex庫

dependencies { ... compile 'com.android.support:multidex:' ... }

第2步 
在buildType或productFlavor中開啓multiDexEnabled。

defaultConfig { ... multiDexEnabled true ... }

現在,根據你的項目情況,你有3種選擇:

  1. 如果你沒有創建自己的Application 類,在你的清單文件AndroidManifest.xml中配置android.support.multidex.MultiDexApplication就可以了。

    .... android:name="android.support.multidex.MultiDexApplication" ...

  2. 如果你有自己的Application類了,讓它繼承 android.support.multidex.MultiDexApplication而不是android.app.Application
  3. 如果你的Application繼承了其他的類,並且你不想改變或者沒辦法改變。按照下面的方法重寫attachBaseContext()

    public class MyApplication extends FooApplication { @Override protected void attachBaseContext(Context base) { super.attachBaseContext(base); MultiDex.install(this); } }

不論你選擇上面哪種,都會創建多個大小差不多的dex文件代替單個龐大的dex文件。運行的時候回同事加載所有的這些dex文件。

當年編譯app的時候,Gradle會生成很多個dex文件和一個apk文件讓你可以在設備或者模擬器上運行。

enter image description here
你可以從這個項目看到上面的效果

注意事項

Out of memory 問題 
對於有很多依賴的項目,編譯可能因爲下面的錯誤中斷

Error:Execution failed for task ':app:dexDebug'. ... Error Code: 3 Output: UNEXPECTED TOP-LEVEL ERROR: java.lang.OutOfMemoryError: GC overhead limit exceeded at com.android.dx.cf.cst.ConstantPoolParser.parse0(ConstantPoolParser.java:326) ...

在build.gralde android標籤下面添加下面代碼可以解決

dexOptions { incremental true javaMaxHeapSize "4g" }

應用啓動緩慢 
根據我們的經驗,添加了這個支持庫以後,大多數情況下都正常了。這對某些設備,比如Kindle Fire上面,應用啓動會比之前慢很多。加載所有的類在應用一啓動的時候會花費大量的時間。這就會導致黑屏一段時間,甚至導致ANR.

更多推薦方案點擊這裏

結論

這個雖然在大多數時候可以解決DEX 64K的問題,但是應該是保留使用。當你嘗試使用它以前,請先嚐試刪除不需要的依賴並且使用ProGuard混淆,如果你必須要使用這個方案。請確保在舊設備上做了測試。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章