1 前言
Android APP 啟動優化是性能優化的重要方向之一,特别是對于原生應用來講,控制在1s内以内對一個APP的競争力很重要,下面從幾個角度來講APP的啟動優化,先看APP的啟動類别
2 APP啟動類别
參考google官方文檔App startup time,官方對APP啟動主要做了三種分類
1.冷啟動
冷啟動指的是APP從頭開始啟動,沒有建立程序,需要完整的走程序建立,ActivityThread建立,Application建立等生命周期的啟動,冷啟動耗時最多
啟動時分為以下幾步
1 加載和啟動app
2 加載空白window
3 建立App程序
随後進行如下步驟
1 建立Application對象,并回調其方法
2 啟動主線程
3 建立MainActivity
4 初始化View和加載布局
5 布局螢幕
6 首幀繪制
冷啟動一般流程如下:
2.暖啟動
當應用中的Activity被銷毀,但在記憶體中常駐時,應用的啟動方式就會變為暖啟動。相比冷啟動,暖啟動過程減少了對象初始化、布局加載等工作,啟動時間更短。但啟動時,系統依然會展示一個空白背景,直到第一個Activity的内容呈現為止。是以暖啟動一般會走Activity的onCreate生命周期,暖啟動耗時較少,一般需要注意在Activity的生命周期中不要做耗時操作即可。
3.熱啟動
相比暖啟動,熱啟動時應用做的工作更少,啟動時間更短。熱啟動産生的場景很多,常見如:使用者使用傳回鍵退出應用,然後馬上又重新啟動應用。熱啟動較快,一般需要注意在onResmue中不要做耗時操作
對于系統流程我們一般無法改變,是以對于三方應用來說,APP啟動優化的主要方向在Application的生命周期和Activity的生命周期中
3 APP啟動測量
前面講了APP啟動的類别,現在要講如何粗略或者詳細的測量一個APP的啟動時間,一般來說有以下幾種辦法
1 adb 指令測量
adb shell am start –W packageName/首屏Activity
例如:
adb shell am start –W com.qiyei.mall/com.qiyei.mall.ui.activity. MainActivity
執行如下:
MainActivity 是首頁,HomeActivity是首頁
ThisTime: 最後一個Activity啟動耗時
TotalTime: 啟動所有Activity耗時
WaitTime: AMS啟動Activity耗時
2 ActivityManager中日志列印
ActivityManager中會列印啟動activity的時間
ActivityManager: Displayed com.android.myexample/.StartupTiming: +3s534ms (total +1m22s643ms)
相關的代碼如下:
ActivityRecord#reportLaunchTimeLocked()
private void reportLaunchTimeLocked(final long curTime) {
final ActivityStack stack = getStack();
if (stack == null) {
return;
}
final long thisTime = curTime - displayStartTime;
final long totalTime = stack.mLaunchStartTime != 0
? (curTime - stack.mLaunchStartTime) : thisTime;
if (SHOW_ACTIVITY_START_TIME) {
Trace.asyncTraceEnd(TRACE_TAG_ACTIVITY_MANAGER, "launching: " + packageName, 0);
EventLog.writeEvent(AM_ACTIVITY_LAUNCH_TIME,
userId, System.identityHashCode(this), shortComponentName,
thisTime, totalTime);
StringBuilder sb = service.mStringBuilder;
sb.setLength(0);
sb.append("Displayed ");
sb.append(shortComponentName);
sb.append(": ");
TimeUtils.formatDuration(thisTime, sb);
if (thisTime != totalTime) {
sb.append(" (total ");
TimeUtils.formatDuration(totalTime, sb);
sb.append(")");
}
Log.i(TAG, sb.toString());
}
mStackSupervisor.reportActivityLaunchedLocked(false, this, thisTime, totalTime);
if (totalTime > 0) {
//service.mUsageStatsService.noteLaunchTime(realActivity, (int)totalTime);
}
displayStartTime = 0;
stack.mLaunchStartTime = 0;
}
可以看到列印的是,這個時間從應用啟動(建立程序)開始計算,到完成視圖的第一次繪制的時間
3 手動打點
這個思想也比較簡單,由于應用層能接觸到的最早方法是Application#attachBaseContext()而結束時間,我們可以認為是Activity#onWindowFocusChanged或者View的真正繪制完成,是以我們可以在attachBaseContext記錄一下時間,在onWindowFocusChanged中或者View繪制完成後記錄結束時間,隻是需要注意怎麼處理View的onDraw監聽問題
4 Systrace測量
這個可以參考官方文章systrace來進行操作,注意systrace需要python環境,是以需要先搭建好python環境。下面是一個systrace的例子
可以看到,systrace可以看到更多的系統調用過程,例如這裡可以看到程序Zygote建立和ActivityThread的初始化時間等,有助于分析啟動時當時系統的狀态。
這一篇就介紹到這,下一篇會介紹TraceView和Systrace的簡單使用