Android 分Dex (MultiDex)

來源:互聯網
上載者:User

標籤:

需要分Dex的理由想必大家都知道了.正是在ART以前的Android系統中,Dex檔案對於方法索引是用一個short類型的資料來存放的.而short的最大值是65535,因此當項目足夠大包含方法數目足夠多超過了65535(包括引用的外部Lib裡面的所有方法),當運行App,就會得到如下的錯誤提示.

Unable to execute dex: method ID not in [0, 0xffff]: 65536Conversion to Dalvik format failed: Unable to execute dex: method ID not in [0, 0xffff]: 65536

 

這個致命嚴重的Bug出現後,Android官方就寫了一篇著名的Blog(這篇文章我讀了五六遍,甚至連作者的Google+的照片我都看了兩三次,我還是沒有完全搞明白怎麼Walkaround這個嚴重的問題).

再後來,慢慢發展,有很多能人異士發揮自己的創造力,寫了開源的Lib放在GitHub上分享給其他Android開發人員們使用.HelloMultiDex, Secondary-Dex-Gradle等等.

但是解鈴還須繫鈴人,這種系統性的嚴重致命Bug,當然還是Android官方給出解決方案最讓人放心.終於,我們還是等到了你,MultiDex Offical Solution.

我推薦官方文檔和這篇GitHub的文章一起看會有更好的瞭解,少走彎路.

 

下面說一說使用的步驟:

1. 修改Gradle,匯入‘com.android.support:multidex:1.0.0‘,開啟multiDexEnabled;

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‘}

 

2.修改Application.兩種方法:

   1) 直接把Application替換成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>

  2) 在原來的Application中修改調用MultiDex.install(this);

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

 

到這裡其實MultiDex的配置已經完成了.

但是,實際上下面介紹的幾個問題也非常值得我們關注.

1. 一些在二級Dex載入之前,可能會被調用到的類(比如靜態變數的類),必須放在主Dex中.否則會ClassNotFoundError.

    通過修改Gradle,可以顯示的把一些類放在Main Dex中.

afterEvaluate {    tasks.matching {        it.name.startsWith(‘dex‘)    }.each { dx ->        if (dx.additionalParameters == null) {            dx.additionalParameters = []        }        dx.additionalParameters += ‘--multi-dex‘        dx.additionalParameters += "--main-dex-list=$projectDir/<filename>".toString()    }}

    上面是修改後的Gradle,其中<filename>是一個文字檔的檔案名稱,存放在和這個Gradle指令碼同一級的檔案目錄下.

    而這個文字檔的內容如下.實際就是把需要放在Main Dex的類羅列出來.

android/support/multidex/BuildConfig/classandroid/support/multidex/MultiDex$V14/classandroid/support/multidex/MultiDex$V19/classandroid/support/multidex/MultiDex$V4/classandroid/support/multidex/MultiDex/classandroid/support/multidex/MultiDexApplication/classandroid/support/multidex/MultiDexExtractor$1/classandroid/support/multidex/MultiDexExtractor/classandroid/support/multidex/ZipUtil$CentralDirectory/classandroid/support/multidex/ZipUtil/class

 

2. 如果用使用其他Lib,要保證這些Lib沒有被preDex,否則可能會拋出下面的異常

UNEXPECTED TOP-LEVEL EXCEPTION:    com.android.dex.DexException: Library dex files are not supported in multi-dex mode        at com.android.dx.command.dexer.Main.runMultiDex(Main.java:337)        at com.android.dx.command.dexer.Main.run(Main.java:243)        at com.android.dx.command.dexer.Main.main(Main.java:214)        at com.android.dx.command.Main.main(Main.java:106)

   遇到這個異常,需要在Gradle中修改,讓它不要對Lib做preDexing

android {//  ...    dexOptions {        preDexLibraries = false    }}

 

3. 如果每次都開啟MultiDex編譯版本的話,會比平常用更多的時間(這個也容易理解,畢竟做了不少事情)

    Android的官方文檔也給了我們一個小小的建議,利用Gradle建立兩個Flavor.一個minSdkVersion設定成21,這是用了ART支援的Dex格式,避免了MultiDex的開銷.而另外一個Flavor就是原本支援的最小sdkVersion.平時開發時候偵錯工具,就用前者的Flavor,發布版本打包就用後者的Flavor.

android {    productFlavors {        // Define separate dev and prod product flavors.        dev {            // dev utilizes minSDKVersion = 21 to allow the Android gradle plugin            // to pre-dex each module and produce an APK that can be tested on            // Android Lollipop without time consuming dex merging processes.            minSdkVersion 21        }        prod {            // The actual minSdkVersion for the application.            minSdkVersion 14        }    }          ...    buildTypes {        release {            runProguard true            proguardFiles getDefaultProguardFile(‘proguard-android.txt‘),                                                 ‘proguard-rules.pro‘        }    }}dependencies {  compile ‘com.android.support:multidex:1.0.0‘}

 

有了Android官方的支援後,MultiDex比最原始的解決方案簡單多了.媽媽再也不用擔心我們要分Dex啦!

Android 分Dex (MultiDex)

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.