### 背景
隨著業(yè)務(wù)快速發(fā)展耸别,各種業(yè)務(wù)功能上線健芭,版本不斷迭代,apk體積也越來越大秀姐。apk體積過大慈迈,一方面會消耗用戶更多的流量,另一方面也會增加包安裝時間省有,進而對于app流量導入產(chǎn)生不利影響痒留。
> 在動手之前,還是要考慮清楚:什么是apk體積過大蠢沿,閾值是多少伸头?建議結(jié)合實際目標用戶群體和市場中類似app想對比,定義一個合適值舷蟀。如果用戶90%都是在WIFI場景下恤磷,而實際包體積只有20M,推斷用戶僅需要20s時間就能安裝完成野宜,相信很多用戶還是愿意去等的扫步。技術(shù)千萬不能為了技術(shù)而技術(shù)。
### Apk構(gòu)成
首先我們看下apk是什么匈子?下面是來自wiki的定義:
> Android應(yīng)用程序包(英語:Android application package河胎,APK)是Android操作系統(tǒng)使用的一種應(yīng)用程序包文件格式,用于分發(fā)和安裝移動應(yīng)用及中間件虎敦。一個Android應(yīng)用程序的代碼想要在Android設(shè)備上運行游岳,必須先進行編譯,然后被打包成為一個被Android系統(tǒng)所能識別的文件才可以被運行其徙,而這種能被Android系統(tǒng)識別并運行的文件格式便是“APK”胚迫。 一個APK文件內(nèi)包含被編譯的代碼文件(.dex 文件),文件資源(resources)唾那, assets访锻,證書(certificates),和清單文件(manifest file)通贞。
通過上面解釋朗若,我們可以大致了解apk的構(gòu)成恼五。實質(zhì)上apk仍然是一個壓縮包昌罩,符合zip標準。在以前灾馒,我們可以把后綴名改成`.zip`再解壓開來進行分析【ビ茫現(xiàn)在AS提供了新的工具可以直接Analyze Apk,在AS中雙擊build目錄下的apk或通過menu中的Build菜單找到apk源文件即可。
我們看一個實際的例子:
通過工具轨功,我們看到各個部分的體積大小旭斥,以及占的百分比,幫助我們優(yōu)化更加有的放矢古涧。
#### dex優(yōu)化
我們知道android應(yīng)用是運行在虛擬機上的垂券,工程編譯過程中會把java、aidl等文件編譯成class羡滑,再轉(zhuǎn)換成dex文件菇爪。如果method或field超過了65k,我們還需要引入multidex分包以保證在dialvik上正常運行柒昏。
常見的優(yōu)化策略有無用代碼刪除凳宙,IDE會把未使用到的區(qū)塊灰色展示,也可以通過lint工具來幫助我們識別到职祷。這個功能在menu中的Analyze的`Run inpection by name`輸入`unused xx`氏涩。甚至是在編譯過程中,我們也可以通過混淆配置來做到有梆,比方說常見的Log刪除是尖。
而隨著業(yè)務(wù)發(fā)展,大型app都進行了模塊化組件化淳梦,不同團隊負責開發(fā)不同模塊析砸。開發(fā)過程極易出現(xiàn)一些重復工具方法,甚至引入相同功能的不同組件爆袍。架構(gòu)上也需要一下規(guī)約工具來限定重復代碼的編寫首繁。
在class轉(zhuǎn)換成dex過程中,我們可以用新一代d8工具陨囊,它可以幫助我們的dex體積更小運行速度更快弦疮。Facebook也開源了一款redex的工具幫助優(yōu)化dex。
#### 資源優(yōu)化
而說到資源必然要說的是圖片優(yōu)化蜘醋,畢竟圖片是資源體積中占大頭胁塞。
我們可以選擇體積更小的圖片,比方說webp格式压语。要注意的是啸罢,webp在4.3以下有一些兼容問題,選擇需謹慎胎食。而對于png也可以采用有損或無損壓縮圖片扰才,常見工具有tingpng或imageoptim等。經(jīng)常png會有一些空白邊距厕怜,這些部分也可以刪除掉衩匣,通過代碼或xml來實現(xiàn)邊距蕾总。
小的icon也可以使用svg格式。一些特定效果也可以通過XML自定義實現(xiàn)琅捏。新手常常有個誤區(qū)生百,就是做.9圖片的原圖依舊很大,既然已經(jīng)讓程序幫我們拉伸了柄延,原圖實際上可以保持很小的體積蚀浆。
經(jīng)常在適配屏幕時,開發(fā)會使用多套圖片搜吧。實際上大部分時候一套圖片就可以搞定了蜡坊,系統(tǒng)會自動幫我們處理圖片縮放。
而在適配不同API時赎败,打包過程也會自動生成多個目錄秕衙。適當選擇最低API格式有好處的,更高版本意味著開發(fā)效率更高僵刮,同時兼容設(shè)備變少据忘,需要同業(yè)務(wù)一起考慮。
打包過程也會生成一個resource.arsc文件搞糕,里面是資源ID的映射關(guān)系勇吊。這個部分也可以通過混淆資源id來優(yōu)化,可以有效減少體積窍仰。
最后同樣的汉规,不需要的資源一定要刪掉。同樣使用lint工具可以幫我們自動刪除驹吮。模塊化也需要當心不同模塊出現(xiàn)同樣的圖片针史。
#### 動態(tài)庫優(yōu)化
在一些需要安全高性能的常見,應(yīng)用中需要采用native來實現(xiàn)碟狞。android平臺提供了適配各種cpu架構(gòu)的可能啄枕,包括x86 arm mips等,包活arm也有v7 v8等族沃。針對不同cpu我們可以選擇打不同包频祝,gradle腳本中通過api也可以限制〈嘌停或者損失一些性能常空,只采用arm最低版本也是可以兼容的。對于某些不常用功能盖溺,我們也能用動態(tài)加載漓糙,運行時再下載so到本地。
### 持之以恒
包體積優(yōu)化需要平常的積累咐柜,點點滴滴細節(jié)摳出來兼蜈。需要每個版本都要注意,而不是到時候來個突擊拙友。需要深入到每個人心中为狸。針對app開發(fā)的生命周期,將一些步驟納入到流程匯總持續(xù)進行優(yōu)化遗契。從開發(fā)到測試再到上線辐棒,甚至是上線后app在設(shè)備上占的磁盤大小。