1. 程式人生 > >構建超過65535方法數的安卓程式

構建超過65535方法數的安卓程式

本文譯自http://developer.android.com/tools/building/multidex.html#about

構建超過65536方法數的安卓程式

 隨著安卓平臺的不斷髮展,安卓應用的大小也在不斷增加。當你的應用和引用庫的大小達到了一定的規模,你會遇到構建的錯誤,錯誤指出,你的應用達到了安卓應用構建架構(build architecture)的限制,早期版本中錯誤資訊如下:

Conversion to Dalvik format failed:
Unable to execute dex: method ID not in [0, 0xffff]: 65536
在最近的版本中,錯誤提示有所不同,但是他們指向了同一個問題
trouble writing output:
Too many field references: 131000; max is 65536.
You may try using --multi-dex option.

這兩個錯誤資訊中出現了一個共同的數字:65536。這個數字是很重要的,他代表了在一個可執行Dalvik(dex)位元組碼檔案中可飲用的方法總數。如果你在構建一個安卓應用程式的時候遇到了這個錯誤,祝賀你,你已經有了相當多的程式碼!這個文件解釋瞭如何越過這個限制從而可以繼續構建你的app。

關於65k的引用限制

安卓應用(APK)檔案包含著以可執行Dalvik(DEX)檔案表示的可執行位元組碼檔案,這個檔案中包含著在app中執行的編譯程式碼。DEX的說明中限制在一個DEX檔案中可被引用的方法總數不能超過65536,包括安卓框架(framework)的方法,庫(library)方法和你自己程式碼中的方法。如果希望超過這個限制則需要在安卓構建的過程中生成多個DEX檔案,我們稱之為multidex配置。

Multidex支援安卓5.0以前的系統

安卓5.0以前的系統版本在Dalvik執行的時候執行y應用程式碼。通常來說,Dalvik限制每個apk檔案只有一個classes,dex位元組碼檔案。為了避開這個限制,我們可以使用multidex支援庫(multidex support library),它成為了你的app中原生DEX檔案的一部分,並且可以管理使用額外的DEX檔案以及這些DEX檔案包含的程式碼。

Multidex支援安卓5.0及更高版本的系統

安卓5.0以及更高版本的系統,通過ART可以直接從APK中載入多個DEX檔案。ART在應用程式安裝的時候會進行預編譯,通過掃描所有的classes(...N).dex檔案,將他們編譯成為一個.oat檔案,從而可以在安卓裝置中執行。如果想了解更多關於安卓5.0的執行機制,請看
關於ART的介紹

避免65k的限制

在配置你的app支援65k或更多的方法引用之前,你應該採取措施減少程式碼中的引用總數,包括程式碼中的方法以及引用的類庫中的方法。下面的幾個策略能夠幫助你們避免dex的引用限制。 審查你的app中直接或間接的依賴-確保任何大型的依賴庫在app中的引用要比在程式中新增大量程式碼更有價值。一個典型的反例就是新增一個很大的依賴庫只因為需要使用其中很少的功能。減少程式碼中的依賴經常可以幫助你避免dex引用限制。 通過混淆器移除未使用的程式碼-安裝混淆器,設定應用執行混淆器,使得app在釋出構建的時候能夠收縮(shrinking),收縮能夠確保未使用的程式碼不會被裝置到APK中。

在Gradle下為你的APP配置Multidex

Gradle的安卓外掛在安卓SDK工具(Android SDK Build Tools)21.1及以上版本支援將multidex作為構建配置的一部分。在試圖為app安配置multidex之前,請確認你使用SDK Managert更新了安卓SDK構建工具以及安卓支援庫到最新版本。 設定你的app開發工程能夠使用multidex配置,需要你對工程做一些修改。特別是你需要執行以下步驟:
  • 改變你的Gradle構建配置使得能夠支援multidex

修改你的app Gradle 構建檔案配置包括支援庫以及能夠輸出multidex,如下所示

android {
    compileSdkVersion 21
    buildToolsVersion "21.1.0"

    defaultConfig {
        ...
        minSdkVersion 14
        targetSdkVersion 21
        ...

        // Enabling multidex support.
        multiDexEnabled true
    }
    ...
}

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

注意:在你的Gradle 構建檔案中,你可以指定multiDexEnabled設定在defaultConfig,buildType, 或者productFlavor或者

在manifest中的application元素中增加來自multidex支援庫中的MultiDexApplication

<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
    package="com.example.android.multidex.myapplication">
    <application
        ...
        android:name="android.support.multidex.MultiDexApplication">
        ...
    </application>
</manifest>
當我們在app中增加了這些配置,安卓構建工具夠早了一個原生的DEX(classes.dex)並且支援(classes2.dex,classes3.dex)等等,構建系統也會將這些資訊打包到apk中。

注意:如果app使用了擴充套件的Application類,你可以覆蓋(override)他的attachBaseContext()方法並且呼叫MultiDex,install(this)從而支援multidex。如需瞭解更多資訊,請參考MultiDexApplication文件。