Android教程網
  1. 首頁
  2. Android 技術
  3. Android 手機
  4. Android 系統教程
  5. Android 游戲
 Android教程網 >> Android技術 >> 關於Android編程 >> Android分包MultiDex原理詳解

Android分包MultiDex原理詳解

編輯:關於Android編程

MultiDex的產生背景

當Android系統安裝一個應用的時候,有一步是對Dex進行優化,這個過程有一個專門的工具來處理,叫DexOpt。DexOpt的執行過程是在第一次加載Dex文件的時候執行的。這個過程會生成一個ODEX文件,即Optimised Dex。執行ODex的效率會比直接執行Dex文件的效率要高很多。

但是在早期的Android系統中,DexOpt有一個問題,DexOpt會把每一個類的方法id檢索起來,存在一個鏈表結構裡面。但是這個鏈表的長度是用一個short類型來保存的,導致了方法id的數目不能夠超過65536個。當一個項目足夠大的時候,顯然這個方法數的上限是不夠的。盡管在新版本的Android系統中,DexOpt修復了這個問題,但是我們仍然需要對低版本的Android系統做兼容。

為了解決方法數超限的問題,需要將該dex文件拆成兩個或多個,為此谷歌官方推出了multidex兼容包,配合AndroidStudio實現了一個APK包含多個dex的功能。


MultiDex的簡要原理

我們以APK中有兩個dex文件為例,第二個dex文件為classes2.dex。

兼容包在Applicaion實例化之後,會檢查系統版本是否支持 multidex,classes2.dex是否需要安裝。 如果需要安裝則會從APK中解壓出classes2.dex並將其拷貝到應用的沙盒目錄下。 通過反射將classes2.dex注入到當前的classloader中。

下面引入一下官方的文檔。

https://developer.android.com/tools/building/multidex.html#about
筆者,針對官方文檔的翻譯如下:

構建超過65K方法的App

隨著Android設備的慢慢發展,App的大小會變得越來越大。當我們在開發App的時候由於報的大小和引用庫的原因,我們在編譯我們項目的時候通常會遇到下面一個錯誤:

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

當然,也有一些系統設備會出現以下log信息,不過反饋的是同一個問題:

trouble writing output:
Too many field references: 131000; max is 65536.
You may try using --multi-dex option.

這兩個錯誤條件顯示一個共同的數字:65536。這個數字,它表示的是你在一個dex包中的函數方法超過了65535個。

如果你已經構建了一個Android App時,並收到了這個錯誤,那麼恭喜你,你有很多代碼!

下面我們就具體說說,如何解決這個問題。


關於65K方法限制

我們知道Android中的可執行偉劍都存儲在dex文件中,其中包含已編譯的代碼來運行你的應用程序。Dalvik虛擬機對可執行dex文件的規格是有方法限制的,即一個單一的dex文件的方法總數最多為65536。

其中包括:

引用的Android Framework方法 library的方法 我們自己書寫代碼的方法。

為了突破這個方法數的限制,我們就提出了一個方案——生成多個dex文件。這個多個dex文件的方案,我們又稱為multidex方案配置。

Multidex支持Android 5.0之前的版本
Android5.0版本的平台之前,Android使用的是Dalvik Runtime執行的程序代碼。默認情況下,限制應用到一個單一的classes.dex。

Dalvik字節碼文件每APK。為了繞過這個限制,你可以使用multidex支持庫,成為你的應用程序的主要部分和DEX文件進行管理,獲得額外的dex文件,它們包含的代碼。

Multidex支持Android 5.0及更高版本
Android 5.0和更高的Runtime 如art,本身就支持從應用的APK文件加載多個DEX文件。art支持預編譯的應用程序在安裝時掃描類(..)。Dex文件編譯成一個單一的Android設備上執行.oat文件。


避免65K限制

當你確定使用multidex的分包策略的時候,請你先確定自己的代碼中都是優秀的。你還需要做以下幾步:

去掉一些未使用的import和library 使用ProGuard去掉一些未使用的代碼

用Gradle配置使用Multidex

Android 的 Gradle插件在 Android Build Tool 21.1開始就支持使用multidex了。

設置你的應用程序開發項目中使用multidex配置,要求你做出一些修改您的應用程序開發項目。:

修改Gradle的配置,支持multidex 修改你的manifest。讓其支持multidexapplication類

修改Gradle的build如下:

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

Tips: 你可以在Gradle配置文件中的 multiDexEnabled 在 defaultConfig、
buildType、productFlavor選項設置。

在manifest文件中,添加MultidexApplication Class的引用,如下所示:



    
        ...
    

當然,如果你重寫了 Application,就對自定義Application的繼承方式做一個修改。


Multidex的方式的局限性

雖然我們開起來multidex是一個極好的東西,但是multidex還是存在自己的局限性,我們在開發測試之前要清楚局限性是什麼:

如果二DEX文件太大,安裝分割dex文件是一個復雜的過程,可能會導致應用程序無響應(ANR)的錯誤。在這種情況下,你應該盡量的減小dex文件的大小和刪除無用的邏輯,而不是完全依賴於multidex。 在Android 4.0設備(API Level 14)之前,由於Dalvik linearalloc bug(問題22586),multidex很可能是無法運行的。如果希望運行在Level 14之前的Android系統版本,請先確保完整的測試和使用。 應用程序使用了multiedex配置的,會造成使用比較大的內存。當然,可能還會引起dalvik虛擬機的崩潰(issue 78035)。 對於應用程序比較復雜的,存在較多的library的項目。multidex可能會造成不同依賴項目間的dex文件函數相互調用,找不到方法。

優化multidex開發和構建

一個multidex的配置,對系統apk的構建、簽名、打包復雜性大大的增加。這就意味著,你每一次的構建過程都是相當耗時的。

為了加快我們的開發速度,加快構建的過程,我們可以在Gradle productFlavors新建出來一個 development flavor 和 production flavor 來滿足我們不同構建需求。

下面是一個列子演示我們如何設置這些flavors在Gradle build文件中:

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

在你完成了傷處的配置修改之後,你配置productFlavor 和 buildType來使用 ,devDebug 變種app。使用這些變種app,可以設置proguard disable、multidex enable方便我們測試。

這些配置需要針對Android Gradle插件做如下操作:

在分包前,編譯應用程序中的每一個module包括依賴項目,這個步驟稱為 pre-dexing。 include每一個dex文件 最重要的是,對於主dex文件,不會做切分。以保證計算速度。

這樣設置既能夠保證我們的最終報是一個使用了multidex模式的,而又不影響我們平時開發的測試效率。


在Android Studio中使用變種App

使用multidex工具構建變種App是非常方便的。在Android Studio允許我們選擇這種變種構建方式的接口。

使用Android Studio構建 “devDebug”構建變種app需要完成兩步:

打開變種編輯窗口,選擇favorites選項。 點擊編譯不同的變種,如下圖所示
\

/*
* @author zhoushengtao(周聖韬)
* @since 2015年9月9日 上午 10:31:00
* @weixin stchou_zst
* @blog http://blog.csdn.net/yzzst
* @交流學習QQ群:341989536
* @私人QQ:445914891
/
這裡寫圖片描述

版權聲明:轉載請標注:http://blog.csdn.net/yzzst 。 本文為博主原創文章,未經博主允許不得轉載。

  1. 上一頁:
  2. 下一頁:
熱門文章
閱讀排行版
Copyright © Android教程網 All Rights Reserved