項目地址:github.com/didi/booste…android
Booster 是一款專門爲移動應用設計的易用、輕量級且可擴展的質量優化框架,其目標主要是爲了解決 APP 複雜度的提高而帶來的性能、穩定性、包體積等問題。git
質量優化是全部應用開發者都要面臨的問題,對於 DAU 千萬級的 APP 來講,萬分之一的崩潰率就意味着上千的用戶受到影響,對於長時間在線的司機來講,司機端 APP 的穩定性關乎着司機的安全和收入,因此更是不容小覷。github
隨着業務的快速發展,業務複雜度不斷提高,咱們開始思考:web
基於這些考慮,Booster 應運而生,通過一年多的時間不斷打磨,Booster 成績斐然。因爲目前在質量優化方面基於靜態分析的開源項目屈指可數,加上質量優化對於 APP 開發者而言門檻偏高,所以,咱們選擇了將 Booster 開源,但願更多的開發者和用戶能從中受益。安全
爲了支持差別化的優化需求,Booster 實現了模塊的動態加載,以便於開發者能在不使用配置的狀況下選擇使用指定的模塊,詳見:booster-task-all、booster-transform-all。bash
Booster 在進行優化的過程當中,可能須要注入一些特定的類或者類庫,爲了解決注入類的依賴管理問題,Booster 提供了VariantProcessor SPI 讓開發者能夠輕鬆的擴展,請參考:ThreadVariantProcessor.kt#L12多線程
APP 的卡頓率是衡量應用運行時性能的一個重要指標,爲了能提早發現潛在的卡頓問題,Booster 經過靜態分析實現了性能檢測,並生成可視化的報告幫助開發者定位問題所在,以下圖所示:app
其實現原理是經過分析全部的 class 文件,構建一個全局的 Call Graph, 而後從 Call Graph 中找出在主線程中調用的鏈路(Application
、四大組件、View
、Widget
等相關的方法),而後再將這些鏈路以類爲單位分別輸出報告。框架
詳見:booster-transform-lint。maven
業務線衆多的 APP 廣泛存在線程過載的問題,而線程管理一直是開發者最頭疼的問題之一,雖然能夠經過制定嚴格的代碼規範來歸避此類問題發生,可是對於組織結構複雜的大廠來講,實施起來成本巨大,而對於第三方 SDK 來講,代碼規範則有些力不從心。爲了完全的解決這一問題,Booster 經過在編譯期間修改字節碼實現了全局線程池優化,並對線程進行重命名。
如下是示例代碼:
class MainActivity : AppCompatActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
getSharedPreferences("demo", MODE_PRIVATE).edit().commit()
}
override fun onStart() {
super.onStart()
Thread({
while (true) {
Thread.sleep(5)
}
}, "#Booster").start()
}
override fun onResume() {
super.onResume()
HandlerThread("Booster").start()
}
}
複製代碼
線程重命名效果以下圖所示:
對於 Android 開發者來講,SharedPreferences
幾乎無處不在,而在主線程中修改 SharedPreferences
會致使卡頓甚至 ANR,爲了完全的解決這一問題,Booster 對 APP 中的指令進行了全局的替換。
詳見:booster-transform-shared-preferences。
不管是資源索引,仍是其它常量字段,在編譯完成後,就沒有存在的價值了(反射除外),所以,Booster 將對資源索引字段訪問的指令替換爲常量指令,將其它常量字段從類中刪除,一方面能夠提高運行時性能,另外一方面,還能減少包體積,資源索引(R)表面上看起來微不足道,實際上佔用很多空間,以滴滴車主爲例,資源索引相關的類就有上千個,進行常量字段刪除後,減少了 1MB 左右。
爲了完全解決在 Android 7.1 中存在的bug: 30150688,Booster 對 APP 中的 Toast.show()
方法調用指令進行全局替換。
APP 的包體積也是一個很是重要的指標,在 APP 安裝中,圖片資源佔了至關大的比例,一般狀況下,圖片質量下降 10%-20% 並不會影響視覺效果,所以,Booster 採用有損壓縮來下降圖片的大小,並且,圖像尺寸越小,加載速度越快,佔用內存越少。
Booster 提供了兩種壓縮方案:
兩種方案各有優缺點,pngquant
的方案不存在兼容性問題,可是壓縮率略遜於 WebP,而 WebP 存在系統版本兼容性問題,總的來看,有損壓縮的效果很是顯著,以滴滴車主爲例,APP 包體積減少了 10 MB 左右。
另外,像 Android Support Library 中包含有大量的圖片資源,並且支持多種屏幕尺寸,對於 APP 而言,相同的圖片資源,保留最大尺寸的便可。以 Android Support Library 爲例,去冗餘後,APP 包體積減少了 1MB 左右。
爲了解決 WebView
初始化致使的卡頓問題,Booster 經過注入指令的方式,在主線程空閒時提早加載 WebView
。
除上以上特性外,Booster 還提供了一些輔助開發的功能,如:檢查依賴項中是否包含 SNAPSHOT 版本等等。
在 buildscript
的 classpath 中引入 Booster 插件,而後啓用該插件:
buildscript {
ext.booster_version = '0.4.3'
repositories {
google()
mavenCentral()
jcenter()
}
dependencies {
classpath "com.didiglobal.booster:booster-gradle-plugin:$booster_version"
classpath "com.didiglobal.booster:booster-task-all:$booster_version"
classpath "com.didiglobal.booster:booster-transform-all:$booster_version"
}
}
apply plugin: 'com.android.application'
apply plugin: 'com.didiglobal.booster'
複製代碼
而後經過執行 assemble
task 來構建一個優化過的應用包:
$ ./gradlew assembleRelease
複製代碼
構建完成後,在 build/reports/
目錄下會生成相應的報告:
build/reports/
├── booster-task-compression
│ └── release
│ └── report.txt
├── booster-transform-lint
│ └── release
│ ├── com
│ └── org
├── booster-transform-shared-preferences
│ └── release
│ └── report.txt
├── booster-transform-shrink
│ └── release
│ └── report.txt
├── booster-transform-thread
│ └── release
│ └── report.txt
└── booster-transform-toast
└── release
└── report.txt
複製代碼