AndroidStudio利用android-support-multidex解決64k的各種異常
64k的各種異常
當(dāng)你的應(yīng)用程序和庫引用達(dá)到一定規(guī)模,你遇到構(gòu)建錯(cuò)誤顯示你的應(yīng)用已經(jīng)達(dá)到了一個(gè)Android應(yīng)用程序構(gòu)建體系結(jié)構(gòu)的限制。早期版本的構(gòu)建系統(tǒng)報(bào)告這個(gè)錯(cuò)誤如下:
Conversion to Dalvik format failed:
Unable to execute dex: method ID not in [0, 0xffff]: 65536
或者
UNEXPECTED TOP-LEVEL EXCEPTION:
java.lang.IllegalArgumentException: method ID not in [0, 0xffff]: 65536
at com.android.dx.merge.DexMerger$6.updateIndex(DexMerger.java:501)
at com.android.dx.merge.DexMerger$IdMerger.mergeSorted(DexMerger.java:282)
at com.android.dx.merge.DexMerger.mergeMethodIds(DexMerger.java:490)
at com.android.dx.merge.DexMerger.mergeDexes(DexMerger.java:167)
at com.android.dx.merge.DexMerger.merge(DexMerger.java:188)
at com.android.dx.command.dexer.Main.mergeLibraryDexBuffers(Main.java:439)
at com.android.dx.command.dexer.Main.runMonoDex(Main.java:287)
at com.android.dx.command.dexer.Main.run(Main.java:230)
at com.android.dx.command.dexer.Main.main(Main.java:199)
at com.android.dx.command.Main.main(Main.java:103)
最新版本的Android構(gòu)建系統(tǒng)顯示一個(gè)不同的錯(cuò)誤,但是是同樣一個(gè)問題:
trouble writing output: Too many field references: 131000; max is 65536. You may try using --multi-dex option.
或者
Error:The number of method references in a .dex file cannot exceed 64K.
上面的錯(cuò)誤顯示一個(gè)共同的數(shù)字:65536。這個(gè)數(shù)字是重要的,它代表了引用的總數(shù),可以在單個(gè)調(diào)用的代碼Dalvik可執(zhí)行(Dex)字節(jié)碼文件。如果你的Android應(yīng)用發(fā)生這個(gè)錯(cuò)誤,恭喜你,你的代碼已經(jīng)達(dá)到了一定的量!本文解釋了如何解決這個(gè)限制并繼續(xù)構(gòu)建應(yīng)用程序。
關(guān)于64 k引用限制
Android應(yīng)用程序(APK)在Dalvik可執(zhí)行文件的形式包含可執(zhí)行的字節(jié)碼文件(DEX)文件,其中包含已編譯的代碼來運(yùn)行你的應(yīng)用程序。Dalvik可執(zhí)行規(guī)格限制一個(gè)Dex文件包含65536個(gè)方法:包括Android框架方法、Library方法的總數(shù)、和你自己的代碼方法總數(shù)。因?yàn)?5536等于64×1024,這一限制被稱為“64k引用限制”。
這個(gè)極限就要求我們配置應(yīng)用程序的構(gòu)建過程,需要生成多個(gè)DEX文件,所以稱為multidex 配置。
分析原因與注意事項(xiàng)
解決方法分Android 5.0及以上系統(tǒng)和5.0以下系統(tǒng)怎么做??凸賯儾灰?,先看我一個(gè)個(gè)分析原因,畢竟我要裝下逼哈哈。
一、Android 5.0以下的版本
Android 5.0(API leve 21)之前的系統(tǒng)使用Dalvik執(zhí)行應(yīng)用程序代碼。默認(rèn)情況下,Dalvik限制一個(gè)apk只有一個(gè)Dex文件。為了繞過這個(gè)限制, 我們可以使用multidex support library,它成為我們APK的主要DEX文件的一部分,負(fù)責(zé)管理我們APK訪問其他DEX文件和代碼。
注意: 如果咱的項(xiàng)目minSdkVersion是20或更低,運(yùn)行到Android 4.4(API leve 20)或者更低版本的設(shè)備上時(shí)需要禁用AndroidStudio的即時(shí)運(yùn)行
二、Android 5.0和更高版本
Android 5.0(API leve 21)和更高的系統(tǒng)使用runtime是ART ,原生支持從應(yīng)用的apk文件加載多個(gè)DEX文件。ART在安裝應(yīng)用時(shí)預(yù)編譯應(yīng)用程序,會(huì)掃描多個(gè)classes(..N).dex文件編譯成一個(gè).oat的文件。更多Android5.0 runtime的更多信息,請(qǐng)參見即時(shí)運(yùn)行-instant-run。
注意: 如果你使用即時(shí)運(yùn)行 , AndroidStudio自動(dòng)配置你的應(yīng)用程序,你應(yīng)用程序的minSdkVersion應(yīng)該設(shè)置為21或更高。因?yàn)榧磿r(shí)只工作在你APP的Debug版本,你任然需要配置你的release版本構(gòu)建時(shí)用multidex避免64k的限制。
盡量避免64k限制
在配置我們的App啟用64k或者更多方法引用之前,我們可以減少應(yīng)用代碼內(nèi)的調(diào)度總數(shù),包括我們自身應(yīng)用的方法和第三方的庫,下面的幾個(gè)策略或許可以幫到你:
•檢查你的APP的直接和間接的過度依賴關(guān)系:有時(shí)候我們用到某個(gè)Libaray的某幾個(gè)方法或者功能時(shí)這個(gè)庫非常大,減少這種依賴可能對(duì)與避免64k的問題非常有效。
•在正式打包構(gòu)建的時(shí)候,使用代碼混淆器ProGuard混淆移除未使用的代碼,也就是不把沒有使用的代碼打包到我們的apk中。
使用上面的方法可以幫助我們避免在應(yīng)用程序中生成太多無用的方法和減小我們apk的大小,這對(duì)于用自己服務(wù)器做app更新升級(jí)的同學(xué)是非常有幫助的。
這里給大家推薦下任玉剛同學(xué)的插件式開發(fā)框架:https://github.com/singwhatiwanna/dynamic-load-apk,共同參與開發(fā)者:田嘯,宋思宇。
解決64k問題
在Android SDK Build Tools 21.1或者更高版本的build工具中用Android plugin gradle。確保你更新Android SDK build tools和Android support到最新版本,然后用multidex配置應(yīng)用程序。我們必須要做兩步。
第一步,修改主module的build.gradle文件
在gradle中依賴multidex,并啟用multiDexEnable:
android {
compileSdkVersion 21
buildToolsVersion
defaultConfig {
...
minSdkVersion 14
targetSdkVersion 21
...
// Enabling multidex support.
multiDexEnabled true
}
...
}
dependencies {
compile 'com.android.support:multidex:1.0.1'
}
第二步,繼承android.support.multidex.MultiDexApplication類
兩種情況
第一種情況,如果我們的APP沒有重寫過Application類,我們直接繼承MultiDexApplication,然后在manifest.xml中注冊(cè)Application即可。
第二種情況,如果我們已經(jīng)重寫過Application類,重寫attachBaseContext(Context)方法,并調(diào)用MultiDex.install(this);即可:
protected void attachBaseContext(Context base) {
super.attachBaseContext(base);
MultiDex.install(this);
因?yàn)槲曳^MultiDexApplication的源碼了,里面就是重寫了這個(gè)方法而已哈哈:
public class MultiDexApplication extends Application {
public MultiDexApplication() {
}
protected void attachBaseContext(Context base) {
super.attachBaseContext(base);
MultiDex.install(this);
}
}
注冊(cè)Application
<?xml version= encoding=?> <manifest xmlns:android= package=> <application ... android:name="剛才重寫的Application全類名"> ... </application> </manifest>
multidex庫的一些限制因素
•DEX文件安裝到設(shè)備的過程非常復(fù)雜,如果第二個(gè)DEX文件太大,可能導(dǎo)致應(yīng)用無響應(yīng)。此時(shí)應(yīng)該使用ProGuard減小DEX文件的大小。
•由于Dalvik linearAlloc的Bug,應(yīng)用可能無法在Android 4.0之前的版本啟動(dòng),如果你的應(yīng)用要支持這些版本就要多執(zhí)行測(cè)試。
•同樣因?yàn)镈alvik linearAlloc的限制,如果請(qǐng)求大量內(nèi)存可能導(dǎo)致崩潰。Dalvik linearAlloc是一個(gè)固定大小的緩沖區(qū)。在應(yīng)用的安裝過程中,系統(tǒng)會(huì)運(yùn)行一個(gè)名為dexopt的程序?yàn)樵搼?yīng)用在當(dāng)前機(jī)型中運(yùn)行做準(zhǔn)備。dexopt使用LinearAlloc來存儲(chǔ)應(yīng)用的方法信息。Android 2.2和2.3的緩沖區(qū)只有5MB,Android 4.x提高到了8MB或16MB。當(dāng)方法數(shù)量過多導(dǎo)致超出緩沖區(qū)大小時(shí),會(huì)造成dexopt崩潰。
•Multidex構(gòu)建工具還不支持指定哪些類必須包含在首個(gè)DEX文件中,因此可能會(huì)導(dǎo)致某些類庫(例如某個(gè)類庫需要從原生代碼訪問Java代碼)無法使用。
使用了multidex后的構(gòu)建優(yōu)化
一、因此如果應(yīng)用中包含lirary工程,可能會(huì)發(fā)生如下錯(cuò)誤:
UNEXPECTED TOP-LEVEL EXCEPTION:
com.android.dex.DexException: Library dex files are not supported in multi-dex mode
這個(gè)時(shí)候我們需要禁用預(yù)編譯:
android {
...
dexOptions {
preDexLibraries = false
}
...
}
二、如果在運(yùn)行的時(shí)候遇到如下錯(cuò)誤:
UNEXPECTED TOP-LEVEL ERROR:
java.lang.OutOfMemoryError: Java heap space
我們需要加大java堆內(nèi)存大?。?/p>
maxProcessCount 4 // this is the default value
javaMaxHeapSize "2g"
三、提升運(yùn)行速度
在Android leve 21或者更高SDK版本。使用ART-supported格式生成multidex輸出更快,為我們節(jié)省時(shí)間,所以我們不必在調(diào)試的使用也兼容到5.0以下,所以我們配置最低版本的時(shí)候做個(gè)如下兼容:
android {
productFlavors {
// 自定義偏好設(shè)置.
dev {
// 在Android leve 21或更高版本編譯更快
minSdkVersion 21
}
prod {
// 真正的生產(chǎn)環(huán)境.
minSdkVersion 14
}
}
...
}
dependencies {
compile 'com.android.support:multidex:1.0.1'
}
Android plugin Gradle版本低于1.1怎么辦
你需要添加 以下依賴 multidex-instrumentation :
dependencies {
androidTestCompile('com.android.support:multidex-instrumentation:1.0.1') {
exclude group: 'com.android.support', module: 'multidex'
}
}
Eclipse Jar包下載:http://xiazai.jb51.net/201609/yuanma/androidsupportmultidex(jb51.net).rar
官方參考文檔:https://developer.android.com/tools/building/multidex.html
以上就是本文的全部內(nèi)容,希望對(duì)大家的學(xué)習(xí)有所幫助,也希望大家多多支持腳本之家。
- Android跨進(jìn)程拋異常的原理的實(shí)現(xiàn)
- Android7.0自動(dòng)更新適配 包解析異常
- Android編程實(shí)現(xiàn)項(xiàng)目中異常捕獲及對(duì)應(yīng)Log日志文件保存功能
- Android Studio升級(jí)到3.0 Terminal 中文顯示異常解決
- Android 全局異常捕獲實(shí)例詳解
- android 捕捉異常并上傳至服務(wù)器的簡單實(shí)現(xiàn)
- Android Studio下載更新Android SDK網(wǎng)絡(luò)異?;驘o法下載
- Android 中Crash時(shí)如何獲取異常信息詳解及實(shí)例
- Android異常 java.lang.IllegalStateException解決方法
- 安卓中出現(xiàn)過的一些容易被忽略的異常整理
相關(guān)文章
Android實(shí)現(xiàn)閱讀進(jìn)度記憶功能
這篇文章主要介紹了Android實(shí)現(xiàn)閱讀進(jìn)度記憶功能,Android控件WebView實(shí)現(xiàn)保存閱讀進(jìn)度,具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2017-10-10
Android RadioButton 圖片位置與大小實(shí)例詳解
這篇文章主要介紹了Android RadioButton 圖片位置與大小實(shí)例詳解的相關(guān)資料,這里提供實(shí)例代碼及實(shí)現(xiàn)效果圖,需要的朋友可以參考下2016-11-11
Android 使用jQuery實(shí)現(xiàn)item點(diǎn)擊顯示或隱藏的特效的示例
本篇文章主要介紹了Android 使用jQuery實(shí)現(xiàn)item點(diǎn)擊顯示或隱藏的特效的示例,具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2018-03-03
使用PlatformView將?Android?控件view制作成Flutter插件
這篇文章主要為大家介紹了使用PlatformView將?Android?控件view制作成Flutter插件實(shí)現(xiàn)示例,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪2022-11-11
Android實(shí)現(xiàn)水波紋外擴(kuò)效果的實(shí)例代碼
微信曾經(jīng)推出了一個(gè)查找附近好友的功能,大致功能是這樣的:屏幕上有一個(gè)按鈕,長按按鈕的時(shí)候,會(huì)有一圈圈水波紋的動(dòng)畫向外擴(kuò)散,松手后,動(dòng)畫結(jié)束2018-05-05
Android實(shí)現(xiàn)通過手勢(shì)控制圖片大小縮放的方法
這篇文章主要介紹了Android實(shí)現(xiàn)通過手勢(shì)控制圖片大小縮放的方法,結(jié)合實(shí)例形式分析了Android控制圖片縮放的原理、實(shí)現(xiàn)步驟與相關(guān)操作技巧,需要的朋友可以參考下2016-10-10
使用ViewPager實(shí)現(xiàn)左右循環(huán)滑動(dòng)及滑動(dòng)跳轉(zhuǎn)
今天實(shí)現(xiàn)了左右滑動(dòng),至于在最后一頁滑動(dòng)跳轉(zhuǎn),這個(gè)也做了但是效果不是太好,也希望有實(shí)現(xiàn)的朋友能夠分享下2013-01-01
Android圖片三級(jí)緩存的原理及其實(shí)現(xiàn)
本篇文章主要介紹了Android圖片三級(jí)緩存的原理及其實(shí)現(xiàn),小編覺得挺不錯(cuò)的,現(xiàn)在分享給大家,也給大家做個(gè)參考。一起跟隨小編過來看看吧2017-09-09

