多Dex加載方案對比

隨着業務擴張,代碼量越來越大,apk中單個dex方法數超過65K,就需要dex分包,Google官方推出了MultiDex來解決65K的問題,區分不同的Android虛擬機,會有一些問題。

Dalvik上,使用JIT(just in time),應用運行時,需要先將dex轉換成os上可以運行的機器碼,在此過程中,還會對dex文件進行優化(dexopt),因此在應用第一次啓動時,會經歷這些過程,apk解壓->dexopt->加載dex->字節碼轉換->啓動,在加載dex過程中,安裝第二個dex之後的dex涉及到io操作,在dex加載完成之前,應用需要一直等待,此過程耗時較長,如果dex文件過大,還會造成ANR;

ART上,使用oat(Ahead of time),在應用安裝時,dex就會被解壓優化完成,轉換成可執行的機器碼,之後應用在啓動時,只需要加載機器碼即可,所以不會出現啓動ANR的問題。

爲了解決Dalvik上冷啓動慢的問題,通常的方法是自定義第二個dex的加載流程,常用方案有以下幾種:

方案

原理

接入技術難度

優點

不足

風險

方案

原理

接入技術難度

優點

不足

風險

Google MultiDex

第一個啓動的進程的主線程上解壓安裝,同步執行,dex全部安裝完成之後,啓動應用

最簡單

dex加載完成之後,應用才真正開始運行,不會出現NoClassDefFoundError

啓動慢

dex文件過大時,在低配設備上可能會出現ANR、黑屏

微信/QQ

1、將dex文件放在assets文件夾下,加載前校驗md5(官方沒校驗);

2、四大組件的直接間接依賴都直接放在主dex中;

3、判斷是否已經dexopt,若已經dexopt,即放在attachBaseContext加載,反之放於地球中用線程加載(若判斷revision改變,即將dex以及dexopt目錄清空。只需簡單判斷兩個目錄dex名稱、數量是否與配置文件的一致)

最複雜,需要自己寫腳本掃描依賴集,以及自定義dex加載過程

啓動不會發生ANR,比Google的MultiDex更快

太過複雜,每次都需重新掃描依賴集,而且使用的是比較大的間接依賴集

Facebook

1、使用自己開源的buck進行dex分包;

2、將加載Dex的邏輯放於單獨的nodex進程,這是一個非常簡單、輕量級的進程。它沒有任何的ContentProvider,只有有限的幾個Activity、Service;

3、將啓動LauncherActivity放在nodex進程,啓動時在nodex進程中安裝dex,主進程一直等待,dex安裝完成之後,啓動應用;

比Google的MultiDex稍複雜一些

依賴集非常簡單,同時首次加載Dex時也不會卡死

啓動主進程之前,必須先啓動nodex進程,額外增加了啓動時間(大約幾百毫秒)

美團

1、使用gradle插件進行分包,編譯期生成dex文件時,將入口Activity直接依賴的類放入主dex中;

2、多dex安裝時,先加載主dex,啓動應用,後續dex異步安裝,安裝完成之後,提供回調方法;

3、hook Activity的啓動過程,如果在異步加載dex期間就引用了未加載的類進行Activity跳轉,啓動一個Loading的頁面,直到所有dex加載完成;

接入很簡單,但是需要徹底解耦,否則主dex的方法數很容易超過65K,編譯不通過

啓動時間最快

有內部RD支持,方便定位問題

需要代碼高度解耦,要改動業務代碼

容易出現NoClassDefFoundError

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