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.update
點此檢視更多相關話題
為了解決這個問題,Android開發社群有人想出了一些
最終,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種選擇:
-
如果你沒有建立自己的Application 類,在你的清單檔案AndroidManifest.xml中配置
android.support.multidex.MultiDexApplication
就可以了。.... android:name="android.support.multidex.MultiDexApplication" ...
- 如果你有自己的Application類了,讓它繼承
android.support.multidex.MultiDexApplication
而不是android.app.Application
-
如果你的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檔案讓你可以在裝置或者模擬器上執行。
你可以從這個專案看到上面的效果
注意事項
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混淆,如果你必須要使用這個方案。請確保在舊裝置上做了測試。