前言
?啟動速度是用戶對于App好用與否的第一印象牲距,如果用戶在打開一個頁面等待時間超過8S,那么用戶將放棄等待购啄,因此啟動速度優(yōu)化是對于一款A(yù)pp來說是重要的環(huán)節(jié)之一睁宰。
啟動分類
?Android啟動方式分為冷啟動歇万、熱啟動、溫啟動勋陪,一般情況下我們做啟動優(yōu)化主要是針對冷啟動做的贪磺。首先我們可以先通過一些方式去獲得啟動的時間,時間測量有ADB命令诅愚、手動打點寒锚、AOP等方式,每一種方式都有各自的特點和使用場景违孝。
冷啟動流程(耗時最長)
launcher->Ipc->Process.start->ActivityThread->bindApplication->Lifecycle->ViewRootImpl
熱啟動流程(耗時最短)
后臺->前臺
1 ADB命令統(tǒng)計時間
?Google提供的啟動時間文章App startup time
1.1 先安裝app到虛擬機(jī)
1.2 使用adb命令
adb shell am start -W 包名/activiti絕對路徑
例如:adb shell am start -W com.example.demo/.MainActivity打開應(yīng)用的MainActivity界面
- 注意:-W 使用的是大寫的W
1.3 查看結(jié)果
Starting: Intent { act=android.intent.action.MAIN cat=[android.intent.category.LAUNCHER]
cmp=com.example.myapplication/.MainActivity }
Status: ok
Activity: com.example.myapplication/.MainActivity
ThisTime: 944
TotalTime: 944
WaitTime: 955
Complete
- ThisTime : 最后一個Activity啟動耗時
- TotalTime : 所有Activity啟動耗時
- WaitTime : AMS啟動Activity的總耗時
?一般情況下ThisTime和TotalTime是相等的刹前。
缺點
?使用ADB命令只能測試某個Activity的打開到初始化完成的時間,但是在真實的場景中有時候并不是只需要啟動一個Activity雌桑,例如有可能先打開一個啟動頁SplashActivity經(jīng)過一段時間的動畫喇喉,再打開真正的首頁,這才是用戶真正等待的時間校坑,使用ADB命令并不能測量出來拣技。因此使用ADB命令來所測量出的時間并不嚴(yán)謹(jǐn)。
?沒有在AndroidManifest.xml
對應(yīng)的Activity聲明中指定為啟動頁
或者屬性沒有android:exported="true"
的Activity不能使用這種命令行的形式計算啟動時間耍目。
2 手動打點
?手動打點就是在啟動開始時和結(jié)束時進(jìn)行埋點操作膏斤,然后計算二者的差值。
?首先要在Application中的onattachBaseContext
方法進(jìn)行開始啟動時間埋點邪驮,這是我們所能接觸到的最早啟動的時間莫辨。
class MyApplication : Application() {
override fun attachBaseContext(base: Context?) {
super.attachBaseContext(base)
CalculatTime.startRecord()
}
override fun onCreate() {
super.onCreate()
}
}
?然后在第一次展示數(shù)據(jù)時,或Feed第一條展示時結(jié)束埋點。
observer = view.getViewTreeObserver();
//注冊觀察者沮榜,監(jiān)聽變化
observer.addOnPreDrawListener(new ViewTreeObserver.OnPreDrawListener() {
@Override
public boolean onPreDraw() {
if(observer.isAlive()){
observer.removeOnPreDrawListener(this);
}
CalculateTime.INSTANCE.endRecord("MainActivity");
return true;
}
});
?注意:這里會存在一個誤區(qū)盘榨,在onWindowFocusChanged進(jìn)行結(jié)束時間的記錄,這是不合適的蟆融。
?我們不僅可以計算用戶真正看到第一幀所消耗的時間较曼,也可以通過手動打點的方式計算時間,其中包括第三方SDK(友盟振愿、百度統(tǒng)計等等)或者其它需要第一時間初始化的框架。
object CalculateTime {
private var startTime: Long = 0
fun startRecord() {
startTime = SystemClock.currentThreadTimeMillis()
}
fun endRecord(tag: String) {
Log.d(tag, "${SystemClock.currentThreadTimeMillis() - startTime}")
}
}
總結(jié)
?啟動時間測量有兩種方式弛饭,一種是ADB命令冕末,另一種是手動打點的方式。手動打點要避免誤區(qū)侣颂,在第一條數(shù)據(jù)展示時才算打點結(jié)束档桃。