Android 遇到方法數上限65536後記錄總結

前言:首先說一下我遇到的情況,最近接手了一個項目是在已有的項目裏進行更新添加一些功能,然後該項目導了N多的包,在我使用Android Studio的run”App”直接安裝到手機上運行是正常的,然後正式打包安裝後就崩潰了,當時覺得很奇怪,然後一看日誌:
trouble writing output:
Too many field references: 131000; max is 65536.
You may try using --multi-dex option.

很明顯,方法數65536上限了,那爲什麼直接運行又沒問題呢?
沒辦法只好查資料:
Note: While using Instant Run, Android Studio automatically configures your app for multidex when your app's minSdkVersion is set to 21 or higher. Because Instant Run only works with the debug version of your app, you still need to configure your release build for multidex to avoid the 64K limit.
大概意思就是:
如果使用Instant Run,當app的minSdkVersion大於或等於21時,Android Studio會自動配置支持multidex,但是僅debug版本有效,release版仍然需要配置multidex來突破64K限制。
原來當android sdk大於21的時候debug自動支持multidex;好了回到正文multidex分包

multidex分包

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

好了,自己也是小白一個也不可能詳細講解MultiDex的原理,就簡單粗暴的到這吧((lll¬ω¬))

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

  • 檢查我們導入的包,去掉一些未使用的import和library,比如說使用高德定位,那我們只需導定位包就行不需要把地圖等包導入
  • 檢查我們自己書寫的代碼,將未使用的代碼刪掉(使用ProGuard去除未使用的方法 -爲release版本配置ProGuard,能有效排除一些無用方法)
  • 檢查我們自己書寫的方法,儘量保證沒有重複的(不要多次造同一個輪子)

上面我們已經確定後任然需要分包的話,那麼久簡單說下官方推薦的方法吧:

第一步:build.gradle文件中添加 一句話 multiDexEnabled = true

defaultConfig {
        applicationId "com.."
        minSdkVersion 15
        targetSdkVersion 25
        versionCode 1
        versionName "1.0"
        multiDexEnabled true
    }

第二步:導入multixdex support包,用來操作引打包過程(很重要)

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

第三步:修改我們自己的Application類,使其繼承 MultiDexApplication 類
你的應用中已有Application,那麼可以直接將繼承Application 改爲繼承MultiDexApplication,而無需修改manifest文件或複寫attachBaseContext()方法。

//已經繼承Application那麼也可以通過複寫attachBaseContext()方法並調用MultiDex.install(this)來支持multidex,即無需修改manifest文件
protected void attachBaseContext(Context base) {
        super.attachBaseContext(base);
        MultiDex.install(this);
    }

如果之前並沒有Application,那麼按以下導入即可:

<?xml version="1.0" encoding="utf-8"?>
<manifest 
    <application
        ...
        android:name="android.support.multidex.MultiDexApplication">
        ...
    </application>
</manifest>

到此分包操作已經完成,我們可以正常release打包安裝了。謝謝各位觀看!如有錯誤請不吝指教。


爲了向別人、向世界證明自己而努力拼搏,而一旦你真的取得了成績,纔會明白:人無須向別人證明什麼,只要你能超越自己。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章