Android教程網
  1. 首頁
  2. Android 技術
  3. Android 手機
  4. Android 系統教程
  5. Android 游戲
 Android教程網 >> Android技術 >> 關於Android編程 >> 關於 Android Dex 方法限制的一些總結

關於 Android Dex 方法限制的一些總結

編輯:關於Android編程

 

Android的編譯過程

 

在了解這個問題之前我們先要來看看Android 應用編譯的過程:

build

  1. IDE中的資源打包工具 (Android Asset Packaging Tool ,即圖中的aapt) 會將應用中的資源文件進行編譯,這些資源文件包括 AndroidManifest.xml文件,為Activity定義的 XML 文件等等。在這個編譯過程中也會產生一個 R.java 文件,這樣你就可以在你的Java代碼中引用這些資源了。
  2. aidl 工具會將你項目中的所有 .aidl 接口轉換成Java接口。
  3. 項目中的所有的Java代碼,包括 R.java.aidl 文件,都會被Java編譯器編譯,然後輸出 .class 文件。
  4. 接著 dex 工具就會把上一步驟產生的 .class 文件轉成 Dalvik 字節碼,也就是 .dex 文件。同時項目中包含的所有第三方類庫和 .class 文件也會被轉換成 .dex 文件,這樣講方便下一步被打包成最終的 .apk 文件。
  5. 所有的不能編譯的資源(比如圖片等等)、編譯後的資源文件和 .dex 文件會被 apkbuilder 工具打包成一個 .apk 文件。
  6. 一旦 .apk 文件被構建好之後,如果要把把它安裝到設備上面去的話,它就必須用一個debug 或者發行key來對這個apk文件簽名。
  7. 最後,如果應用程序已經被簽名成為發行模式的apk,你還需要使用 aipalign工具對 .apk 進行對齊優化。這樣的話可以減少應用程序在設備上的內存消耗。

     

    為什麼會有這個Dex 方法限制

    內部原因:

    我們注意到在第四步的時候,會產生一個.dex 文件。Android 從之前的Dalvik 到現在Android 5.0 默認的ART 運行時環境都能夠執行這個.dex 文件,它們還使用同一套指令集,即Dalvik 指令集。通過這篇關於Android 指令集格式的介紹文章中,我可以知道Dalvik 指令集是使用16位寄存器來保存項目中所有的方法引用,包括第三方的方法:

     

    invoke-kind {vC, vD, vE, vF, vG}, meth@BBBB
    B: method reference index (16 bits)


     

    這就意味著 Android的單個.dex 文件最能引用65536個方法,在這之後的方法就無法引用了。這就是Android Dex 方法限制異常出現的原因,同時因為ART和Dalvik使用同一套指令集,這個限制在ART 運行時環境中也會存在。

    外部原因:

    第三方庫裡面包含太多的方法。這裡就拿Google Play Service和Guava來舉例。很多Android開發者都會用到Google Play Service庫和Guava庫,而你知道它們提供了多少了方法嗎?Google Play Service 5.0裡面就差不多包含了將近20k+方法,Guava提供了將近14k個方法。這個兩個庫就將近占了方法限制數目65536的半壁江山。

    那麼如何解決Android Dex 方法限制這個問題呢?

    老方法

    對於內部原因:

    1. 從上面的描述中我們知道,Android Dex 方法限制是出現在單個.dex 文件中的,那麼我們可以在一個apk中使用多個.dex 文件嗎?可以,Android 官方博客就給出了這個方案。(在Android5.0之前,由於大部分使用的是Dalvik 運行時環境,Dalvik 運行時環境限制一個apk只能包含一個classes.dex文件。)

      對於外部原因:

      1. 使用配置腳本對第三方庫中的方法進行清除;
      2. 使用ProGuard清除項目中無用的方法,不過效果不如上面的。

         

        新方法(官方動作)

        主要思路:使用multidex support library 讓Android5.0之前的版本也能在一個apk裡面包含多個.dex 文件。具體使用方法請參看這篇文章。

        Google不僅在工具上面做出了改進,還把自己的Google Play Service庫也做了一番改動——從Google Play Service 6.5開始開始支持更細精度的依賴管理,也就是說你只需要Google Drive的api,而不需要google game,maps或者wallet等api的支持,那你就可以只引入Google Drive的api即可。這樣可以在很大程度上減少Dex 方法限制出現的幾率

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