Multidex 和 Dex 方法限制
什麼是 dex?
Dex 是編譯 Android Java 程式碼的檔案格式和編碼的名稱。早期版本的 Android 將直接在名為 Dalvik 的虛擬機器中載入和執行 dex
二進位制檔案。更新版本的 Android 使用 Android Runtime(ART)
,它將 dex
檔案視為中間表示,並在執行應用程式之前對其進行進一步編譯。
就智慧手機的使用壽命而言,Dex 是一種非常古老的檔案格式,專為主存在數十兆位元組的裝置而設計。那些日子的設計侷限一直延續至今。
問題:
dex
檔案格式對可在單個二進位制檔案中引用的方法數量進行編碼。由於儲存引用數的檔案格式部分長度為兩個位元組,因此最大方法引用數為 0xFFFF
或 65535.如果應用程式包含的方法引用數超過該數量,則無法編譯。
該怎麼做:
Google 提供瞭解決此問題的方法,稱為 Multidex。它具有編譯時和執行時元件。顧名思義,在編譯時它會在一個或多個 dex
檔案之間劃分程式碼。在執行時,它將教授預設的 ClassLoader
如何從這些檔案中查詢類。
這種方法適用於較新的裝置,但有一些實質性的缺點。它可以顯著增加應用程式啟動時間,而在較舊的裝置上可能會導致 Application Not Responding
失敗。
如果可能的話,應儘量避免使用 Multidex。
如何避免限制:
在配置應用程式以啟用 64K 或更多方法引用之前,你應該採取措施減少應用程式程式碼呼叫的引用總數,包括應用程式程式碼或包含的庫定義的方法。以下策略可以幫助你避免達到 dex 參考限制:
- 檢查應用程式的直接和傳遞依賴關係 - 確保你在應用程式中包含的任何大型庫依賴關係的使用方式超過了新增到應用程式的程式碼量。一個常見的反模式是包含一個非常大的庫,因為一些實用方法是有用的。減少應用程式程式碼依賴性通常可以幫助你避免 dex 參考限制。
- 使用 ProGuard 刪除未使用的程式碼 - 為應用程式配置 ProGuard 設定以執行 ProGuard,並確保為釋出版本啟用了收縮功能。啟用收縮可確保你不會使用 APK 傳送未使用的程式碼。
第一點需要開發人員的勤奮和紀律。合併第三方庫時,必須考慮庫的大小。例如,兩個流行的 JSON 庫是 Jackson 和 Gson。功能上它們非常相似,但 Gson 傾向於在 Android 中看到更多用途。一個原因是,傑克遜的重量約為 9,000 種,而 Gson 的貢獻為 1,900 種。
有幾種工具可以幫助開發人員跟蹤他們的應用程式的大小:
- dexcount-gradle-plugin 報告每個構建中 APK 或 AAR 中的方法引用數
- dex-method-counts 是一個命令列工具,用於計算 APK 中方法引用的數量
- www.methodscount.com 是一項網路服務,可以計算你上傳的任何 APK 中的方法參考。