本文來自網易雲社區android
做者:鄭文git
首先咱們並不在討論車牌號.本文儘可能避免談論重複的技術點,只探討一下multidex提供給咱們的技術啓示。github
multidex技術原理能夠分紅兩個部分:web
在app啓動時,經過Multidex.install api,擴展ClassLoader的dexElements數組來存儲全部dex,這個流程會根據android sdk版本的不一樣作不一樣的處理,整個流程徹底經過反射完成。api
編譯過程當中的分包機制,將app中的class以某種方式將class分佈在多個dex中數組
從multidex的原理,很容易想起目前比較流行的一個代碼熱修復方案策略。安卓App熱補丁動態修復技術介紹 ,qzone的技術思路在社區誕生了不少技術框架,其中知名度最高的就是Nuwa。但客觀的說,nuwa這個項目是徹底達不到產品release的要求。在調研完全部同技術路線開源框架後,咱們決定造個能應用在線上產品的輪子。安全
使用Transform API進行bytecode的植入,支持高版本gradle性能優化
編譯流程的優化,減小了人工干預的過程架構
支持補丁包的簽名驗證,避免被惡意hookapp
兼容網易安所有門的加殼方案
支持ART模式:在art模式下,應用補丁包可能致使地址錯亂,解決方案是將直接引用修改class的相關類都打包進行補丁包,這是目前其餘開源方案沒有作的
MultiDex機制的出現自己是爲了不出現app 65535問題的出現,但隨着業務邏輯的增加,以及不合理的模塊劃分,致使main dex的方法數也超出了65535,這就致使了main dex capacity exceeded異常。
同時,Multidex的接入額外還會對app的啓動性能形成影響。Multidex在install時須要加載dex,首次啓動時還須要作odex的轉換,而這些都是在ui主線程中完成。 根據 Carlos Sessa的測試,啓用multidex後,4.4或如下的設備,app的啓動時間平均會增長15%的時間,更嚴重的狀況,甚至在啓動時候會出現了黑屏。
目前部分app採起的策略是,放棄掉Multidex的,而轉爲插件化的架構。經過將非核心模塊的lazy load,來達到啓動速度的優化,但咱們須要明確的是,並非全部app都彷佛插件化架構,爲了實現啓動加速或熱更新將本耦合的業務邏輯硬生生拆解纔是本末倒置。
在Android的性能優化中,最多見的思路就是異步化,減小UI線程的工做。在應用的交互層面上,app啓動時,幾乎全部app都會有一個SplashActivity。在界面上展現歡迎頁,在後臺進行初始化的業務邏輯。這就給咱們一個啓發,咱們能夠將系統的初始化邏輯,延遲到咱們的業務初始化時間點上。
更加具體的方式是,咱們能夠將Multidex.install異步化,保證主線程的正常進行,待加載完成後通知SplashActivity跳轉到真正的業務主界面。
在MultiDex加載的異步化以後,咱們能夠進行第二步:main dex大小的精簡。
Multidex會在入口Application的attachBaseContext,加載second dex,所以multidex分包的基本原則是:保證app啓動須要的class放置在main dex上。在gradle 1.5以上,multidex經過CreateManifestKeepList和MutidexTransform完成,分包過程能夠分爲三步:
生成manifest_keep.txt
CreateManifestKeepList會解析出AndroidManifest.xml中全部的組件類:包括Activity、Service、Receiver以及ContentProvider,這些類將會和Application入口類一塊兒放在build/intermediates/multi-dex/{flavor}/{buildType}/manifest_keep.txt中
生成maindexlist.txt文件
MutidexTransform會查找manifest_keep.txt中全部類的直接引用類,具體的方式是遍歷類的全部字段類以及方法,查看方法的參數和返回值的類型,將其放保存在maindexlist.txt
生成main dex