日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 运维知识 > Android >内容正文

Android

Android分包方案multidex

發(fā)布時間:2025/5/22 Android 40 豆豆
生活随笔 收集整理的這篇文章主要介紹了 Android分包方案multidex 小編覺得挺不錯的,現(xiàn)在分享給大家,幫大家做個參考.

對于功能越來越復雜的app的兩大問題

  • 一:我們自己應用的方法數(shù)超過了65536?
    我們所說的方法數(shù)限制,這個方法數(shù)包括了jar包,框架,還有我們自己應用的代碼,當我們應用的代碼超過65536時,結(jié)果如下:

    我們看到,顯示我們方法的引用是65579.而引用數(shù)最大是65536,建議我們開啟分包方案。

    二:我們應用的方法數(shù)沒有超過65536,但是加上依賴的jar包,框架等,超過了65536(根據(jù)方案一的結(jié)果,我們應用方法數(shù)是65579,那我們刪掉200個方法,就小于65536)

    報錯如下:

  • 三:方法數(shù)并沒有超過65536,編譯也完成了,但是在android2.3以前的系統(tǒng)安裝的時候,會異常中止安裝。

    這個問題會發(fā)生在Android?2.2以及Android 2.3的設(shè)備上,涉及到一個名為dexopt的程序,全稱dex optimization,即dex文件優(yōu)化程序。在優(yōu)化過程中,dexopt采用一個固定大小的緩沖區(qū)(LinearAlloc)來存儲應用中所有方法的信息,那么之所以會出現(xiàn)在老版本停止安裝,是因為老版本的緩沖區(qū)的大小是5M,而在新版本中,這個緩沖區(qū)的大小是8M或者16M,在老版本中更容易超過這個限制。

    dexopt的執(zhí)行過程是在第一次加載dex文件的時候執(zhí)行的。這個過程產(chǎn)生了一個ODEX文件,全稱Optimised Dex。這個ODEX文件是在安裝過程中從apk里提取出的可運行文件,是優(yōu)化dex產(chǎn)生的,再把apk包里的dex文件刪除,這樣就做到了預先提取。如果沒有ODEX文件,那么系統(tǒng)會從apk包中提取dex然后再運行。所以優(yōu)化后可以加快軟件的啟動速度,預先提取,減少對RAM的占用。

    在早期的Android系統(tǒng)中,dexopt會把每一個類的方法id檢索起來,存在一個鏈表結(jié)構(gòu)里,而這個鏈表的長度是用一個short類型來保存的,導致方法id的數(shù)目不能夠超過65536個。雖然新版本的android系統(tǒng)中,dexopt修復了這個問題,但是老版本的android系統(tǒng)的用戶市場占有率還是占一定比例,還是不能放棄這部分用戶的,所以我們在開發(fā)中需要對老版本的這個問題進行兼容。

2.方法數(shù)越界的解決方案

  • 插件化技術(shù)

    我們可以采用動態(tài)加載部分dex,通過將一個dex拆分成兩個或多個dex,解決方法數(shù)越界的問題。

    插件化是一套重量級的技術(shù)方案,我們需要通過反射來調(diào)用插件的類或方法,要使用一套插件框架來配合,而且插件化適合一些獨立的模塊,兼容性問題往往較多,如果只是用于解決方法數(shù)越界的話,并不是最好的方案。

  • multidex解決方案

    為了解決方法數(shù)越界的問題,Google在2014年提出了multidex的解決方案,這個方案主要是針對AndroidStudio和Gradle編譯環(huán)境的,將一個dex文件拆成兩個或多個dex文件。

    不過需要注意的是multidex有一個版本問題,在Android 5.0以前使用multidex需要手動引入Google提供的android-support-multidex.jar這個jar包。這個jar包我們可以在Android SDK目錄下的extras/android/support/multidex/library/libs下找到。而從Android 5.0開始,Andorid默認支持了multidex。

    所以,我們就需要注意我們的SDK版本了,如果已經(jīng)支持了multidex,而我們又把android-support-multidex.jar放在了項目的libs文件下,就會報錯。

3.在Gradle和代碼中配置使用Multidex

  • 在Gradle中配置使用Multidex

    由于Android的Gradle插件在Android Build Tool 21.1開始支持使用multidex,所以我們需要使用Android Build Tools 21.1及以上版本,修改app目錄下的build.gradle文件,有兩點需要修改。

    (1)在defaultConfig中添加multiDexEnabled true這個配置項。?
    (2)在dependencies中添加multidex的依賴:?
    compile ‘com.android.support:multidex:1.0.0’

    注意buildToolsVersion要高于21.1,配置好如下:?

  • 在Gradle中配置好之后,我們還需要在代碼中加入支持multidex的功能,有三種方案可選

    方案一:在manifest文件中指定Application為MultiDexApplication,如下:

    方案二:寫一個Application類并繼承MultiDexApplication,并在AndroidManifest.xml的application標簽中進行注冊(在application標簽中增加name屬性,并添加自己的Application類名即可),如果不是想重寫MultiDexApplication中一些方法的話,還是方案一更方便些。如下:

    注冊如下:

    方案三:如果不想按方案二繼承,我們可以重寫Application的attachBaseContext方法,注意,這個方法比onCreate方法先執(zhí)行。具體方法是創(chuàng)建一個新類,繼承Application,然后重寫attachBaseContext方法,并在AndroidManifest.xml的application標簽中進行注冊(與方案二注冊相同)如下:

    對于在AndroidManifest.xml中注冊,與方案二的注冊相同。

3.使用Multide分包后兩種情況的結(jié)果

我們的Demo圖如下,我們根據(jù)該圖和dex文件反編譯的結(jié)果分析分包情況。

  • 情況一:方法數(shù)沒有越界?
    我們將方法數(shù)控制在65536以內(nèi),方法數(shù)沒有越界的話,是不會分包的,解壓apk,你會發(fā)現(xiàn)apk里只有一個classes.dex,如下

    將其反編譯后(不知道怎么反編譯的可以看一下這篇博文:http://blog.csdn.net/gaozhan_csdn/article/details/51984056),結(jié)果如下:

    可以發(fā)現(xiàn),我們的類都在這個主dex文件里,并沒有分包。

  • 情況二:方法數(shù)越界

    我們再將方法數(shù)增加到65536以上。解壓apk,結(jié)果如下:?

    對三個dex文件反編譯一下,看看它們里面分別都包含了什么類。?
    classes.dex(主dex)下的類視圖:?

    classes2.dex的類視圖

    classes3.dex的類視圖

    可以發(fā)現(xiàn)Second類和Third類分別在classes2.dex文件和classes3.dex文件里,其他類都在主dex文件里(classes.dex),我們用multidex的確實現(xiàn)了分包從而解決了方法數(shù)越界的問題。

4.使用MultiDex存在的一些問題

1.Application?中的靜態(tài)全局變量會比MutiDex的?instal()方法優(yōu)先加載,所以建議避免在Application類中使用靜態(tài)變量引用main classes.dex文件以外dex文件中的類。 或者這樣解決:

一些在二級Dex加載之前,可能會被調(diào)用到的類(比如靜態(tài)變量的類),需要放在主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,其中是一個文本文件的文件名,存放在和這個build.gradle腳本同一級的文件目錄下,而不是 項目根目錄。可以把這個文本文件起名為multidex.keep,內(nèi)容如下.實際就是把需要放在Main Dex的類羅列出來.

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

project.afterEvaluate標簽在特定的project配置完成后運行,而gradle.projectsEvaluated在所有projects配置完成后運行。 注意afterEvaluate需要放在android{}里,不可放外面。

但是最新的as中,會自動判斷依賴關(guān)系來分dex,比如以下application中: public class MyApp extends MultiDexApplication {public static MutilTest5 mutilTest5 = new MutilTest5();@Overridepublic void onCreate() {super.onCreate();} } 默認情況下,本來MuitlText5要分到class2.dex里面去,但是因為app里靜態(tài)變量需要用到MuitlText5,如果放到class2.dex中會找不到(因為app中靜態(tài)變量初始化會在加載主dex文件之前執(zhí)行),所以會自動放到主dex文件里去 但是如果依靠as自動分析,在你代碼存在反射和native的情況下,也不保證100%正確,如果不正確,還是需要自己配置哪個類放到主dex中

轉(zhuǎn)載于:https://www.cnblogs.com/chenxibobo/p/6076459.html

總結(jié)

以上是生活随笔為你收集整理的Android分包方案multidex的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網(wǎng)站內(nèi)容還不錯,歡迎將生活随笔推薦給好友。