配置方法數超過 64K 的應用
隨著 Android 平臺的持續成長,Android 應用的大小也在增加。當您的應用及其引用的庫達到特定大小時,您會遇到構建錯誤,指明您的應用已達到 Android 應用構建架構的極限。早期版本的構建系統按如下方式報告這一錯誤:
Conversion to Dalvik format failed:
Unable to execute dex: method ID not in [0, 0xffff]: 65536
較新版本的 Android 構建系統雖然顯示的錯誤不同,但指示的是同一問題:
trouble writing output:
Too many field references: 131000; max is 65536.
You may try using --multi-dex option.
這些錯誤狀況都會顯示下面這個數字:65,536。這個數字很重要,因為它代表的是單個 Dalvik Executable (DEX) 字節碼文件內的代碼可調用的引用總數。本頁介紹如何通過啟用被稱為 Dalvik 可執行文件分包的應用配置來越過這一限制,使您的應用能夠構建并讀取 Dalvik 可執行文件分包 DEX 文件。
關于 64K 引用限制
Android 應用 (APK) 文件包含 Dalvik Executable (DEX) 文件形式的可執行字節碼文件,其中包含用來運行您的應用的已編譯代碼。Dalvik Executable 規范將可在單個 DEX 文件內可引用的方法總數限制在 65,536,其中包括 Android 框架方法、庫方法以及您自己代碼中的方法。在計算機科學領域內,術語千(簡稱 K)表示 1024(或 2^10)。由于 65,536 等于 64 X 1024,因此這一限制也稱為“64K 引用限制”。
Android 5.0 之前版本的 Dalvik 可執行文件分包支持
Android 5.0(API 級別 21)之前的平臺版本使用 Dalvik 運行時來執行應用代碼。默認情況下,Dalvik 限制應用的每個 APK 只能使用單個 classes.dex字節碼文件。要想繞過這一限制,您可以使用 Dalvik 可執行文件分包支持庫,它會成為您的應用主要 DEX 文件的一部分,然后管理對其他 DEX 文件及其所包含代碼的訪問。
注:如果您的項目配置時所面向的 Dalvik 可執行文件分包使用的是 minSdkVersion 20或更低版本,并且您將其部署到運行 Android 4.4(API 級別 20)或更低版本的目標設備上,則 Android Studio 會停用 Instant Run。
Android 5.0 及更高版本的 Dalvik 可執行文件分包支持
Android 5.0(API 級別 21)及更高版本使用名為 ART 的運行時,后者原生支持從 APK 文件加載多個 DEX 文件。ART 在應用安裝時執行預編譯,掃描 classesN.dex 文件,并將它們編譯成單個 .oat 文件,供 Android 設備執行。因此,如果您的 minSdkVersion 為 21 或更高值,則不需要 Dalvik 可執行文件分包支持庫。
如需了解有關 Android 5.0 運行時的詳細信息,請參閱 ART 和 Dalvik。
注:如果將應用的 minSdkVersion 設置為 21 或更高值,使用 Instant Run 時,Android Studio 會自動將應用配置為進行 Dalvik 可執行文件分包。由于 Instant Run 僅適用于調試版本的應用,您仍需配置發布構建進行 Dalvik 可執行文件分包,以規避 64K 限制。
規避 64K 限制
在將您的應用配置為支持使用 64K 或更多方法引用之前,您應該采取措施減少應用代碼調用的引用總數,包括由您的應用代碼或包含的庫定義的方法。下列策略可幫助您避免達到 DEX 引用限制:
檢查您的應用的直接和傳遞依賴項 - 確保您在應用中使用任何龐大依賴庫所帶來的好處大于為應用添加大量代碼所帶來的弊端。一種常見的反面模式是,僅僅為了使用幾個實用方法就在應用中加入非常龐大的庫。減少您的應用代碼依賴項往往能夠幫助您規避 dex 引用限制。
通過 ProGuard 移除未使用的代碼 - 為您的版本構建啟用代碼壓縮以運行 ProGuard。啟用壓縮可確保您交付的 APK 不含有未使用的代碼。
使用這些技巧使您不必在應用中啟用 Dalvik 可執行文件分包,同時還會減小 APK 的總體大小。
配置您的應用進行 Dalvik 可執行文件分包
將您的應用項目設置為使用 Dalvik 可執行文件分包配置需要對您的應用項目進行以下修改,具體取決于應用支持的最低 Android 版本。
如果您的 minSdkVersion 設置為 21 或更高值,您只需在模塊級 build.gradle 文件中將 multiDexEnabled 設置為 true,如此處所示:
android {
defaultConfig {
...
minSdkVersion 21
targetSdkVersion 25
multiDexEnabled true
}
...
}
但是,如果您的 minSdkVersion 設置為 20 或更低值,則您必須按如下方式使用 Dalvik 可執行文件分包支持庫:
修改模塊級 build.gradle 文件以啟用 Dalvik 可執行文件分包,并將 Dalvik 可執行文件分包庫添加為依賴項,如此處所示:
android {
defaultConfig {
...
minSdkVersion 15
targetSdkVersion 25
multiDexEnabled true
}
...
}
dependencies {
compile 'com.android.support:multidex:1.0.1'
}
根據是否要替換 Application
類,執行以下操作之一:
如果您沒有替換 Application
類,請編輯清單文件,按如下方式設置 <application>標記中的 android:name:
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.example.myapp">
<application
android:name="android.support.multidex.MultiDexApplication" >
...
</application>
</manifest>
如果您替換了 Application
類,請按如下方式對其進行更改以擴展 MultiDexApplication
(如果可能):
public class MyApplication extends MultiDexApplication { ... }
或者,如果您替換了 Application
類,但無法更改基本類,則可以改為替換 attachBaseContext()
方法并調用 MultiDex.install(this)
來啟用 Dalvik 可執行文件分包:
public class MyApplication extends SomeOtherApplication {
@Override
protected void attachBaseContext(Context base) {
super.attachBaseContext(context);
Multidex.install(this);
}
}
構建應用后,Android 構建工具會根據需要構建主 DEX 文件 (classes.dex) 和輔助 DEX 文件(classes2.dex 和 classes3.dex 等)。然后,構建系統會將所有 DEX 文件打包到您的 APK 中。
運行時,Dalvik 可執行文件分包 API 使用特殊的類加載器來搜索適用于您的方法的所有 DEX 文件(而不是僅在主 classes.dex 文件中搜索)。
原文:https://developer.android.com/studio/build/multidex.html#keep