一,尋找優化方向
做優化時,找到優化方向很重要,畢竟任何事情都是先有方向然後再去實踐的嘛。
先用 Analyze APK 來分析一下經過數個業務版本迭代過後的Apk
其實網上已經有很多Apk優化的經驗了,這裡只是因地制宜地明確一下優化目標:
資源優化
圖片資源(主要優化res)
資源混淆(主要優化META-INFO/MANIFEST.TF)
arsc檔案壓縮,通過將aapt編譯出來的資源二進位制檔案resource.arsc中的resource table對應塊區的值,修改為混淆後資源路徑,從而達到減少位元組數的效果。
通過網路下載非必要的本地資源(音訊、視訊等)。
程式碼方面(主要優化dex檔案)
移除重複引用的第三方庫。
移除重複程式碼塊。
基於位元組碼的dex優化 Proguard And Redex。
是否應該是用7z來對apk進行壓縮?
aapt資源打包時,預設不對".jpg", ".jpeg", ".png", ".gif" 這些圖片格式的檔案進行壓縮優化。為了驗證,我們使用
aapt l -v xxx.apk
指令來,未經過7z壓縮的apk,上述幾種圖片格式的檔案對應的Method都是以Stored
來儲存的,根據Zip的檔案格式中對壓縮方式的描述Compression_methods可以看出這些檔案是沒有壓縮的。所以,我們可以確認,7z進行apk打包,可以帶來一定程度上的size優化。
下面會根據上面兩個方面的優化進行實戰。
二,具體實戰
1.1 優化圖片資源
使用tinypng、pngquant、ImageOptim啥的圖片壓縮工具把res/ 下的所有png圖片全都進行質量壓縮一遍。如果是在Mac下,個人比較推薦用tinypng(有失真壓縮)壓一遍之後,再用ImageOptim(無失真壓縮)壓一遍,這樣可以達到比較大的壓縮效果。
1.2 & 1.3 資源混淆 & arsc檔案壓縮
這裡使用到了微信的一個開源框架AndResGuard,這個框架的原理類似Java Proguard,但是隻針對資源。他會將原本冗長的資源路徑變短,例如將
res/drawable/wechat
變為r/d/a
。這會極大程度的保護我們的資源,同時也會帶來一些優化效果。
將AndResGuard引入專案需要注意的問題
compress
引數對安裝包體積影響很大。若要支援2.2,resources.arsc需保證壓縮前小於1M。keepmapping方式對增量包大小的影響影響並不大,但使用keepmapping方式有利於保持所有版本混淆的一致性。
白名單的新增:1、若想通過getIdentifier方式獲得資源,需要放置白名單中。(通過R.java的引用方式來獲取資源,儘量不要直接使用getIdentifier方式獲取資源,因 為這樣會帶來 Lint等工具的引用檢測失效 等問題。)2、部分手機桌面快捷圖示的實現有問題,務必將程式桌面icon加入白名單3、第三方庫有某些資源不能混淆,否則會crash,詳細請參考
是否與多渠道打包產生互相影響?(因為涉及到使用7z的方式來重打包apk,所以這一步是需要考慮的)
因為resources.arsc 在 APK 安裝之後仍需要被頻繁的讀取,進行壓縮後可能會帶來一些記憶體使用的上升。
2. 優化程式碼
使用
./gradlew dependencies
命令能夠很清晰的看到專案依賴情況(專案依賴太多我就不貼出來了),可以很容地篩選重複依賴。使用Android Studio的Inspector,去檢測無用程式碼塊,引用,定義 等等。
基於位元組碼的優化
Android目前基於位元組碼的優化有兩種方案。
ProGuard
Proguard本身就已經做了不錯的程式碼優化,它的好處不再多說,但是推薦一個開源專案
Facebook推出的一款優化位元組碼的庫,在專案上做了實現,在使用了Proguard,再使用Redex進行dex壓縮,發現兩個dex各小了0.1M,但瀏覽了一下issue,看到一些奇怪的安裝失敗的case,由於效果不太大,且這個庫不是很成熟,所以沒引入。
三,最後
隨著專案業務不斷增多,參與開發人員也不斷變多,不同的編碼習慣和水平也許會帶來一些技術債務和線上隱患,一些程式碼規範如果能夠做起來,也許能夠在程式設計師開發階段將這些債務消化掉。
使用CheckStyle或者Lint自定義規則,在開發階段使用工具進行程式碼規範檢測。
使用git-precommit,在程式碼提交階段,對commit的資源進行引用檢測、對程式碼進行質量檢測