APP應(yīng)用的啟動時間學(xué)習(xí)

1 應(yīng)用啟動場景

事實上 Android 中一個 App 的啟動時間可以準(zhǔn)確計算的.但是要分場景.也就是說要分開游戲和應(yīng)用. 大家都知道,在Android中,游戲開發(fā)和應(yīng)用開發(fā)是兩碼事.所以我們需要分開來說.

1.1 應(yīng)用啟動

我們平時在寫應(yīng)用的時候,一般會指定一個 mainActivity ,用戶在桌面上點擊這個 Activity 的時候,系統(tǒng)會直接起這個

Activity. 我們知道 Activity 在啟動的時候會走 onCreate/onStart/onResume .這幾個回調(diào)函數(shù).

許多書里講過,當(dāng)執(zhí)行完 onResume 函數(shù)之后,應(yīng)用就顯示出來了…其實這是一種不準(zhǔn)確的說法,因為從系統(tǒng)層面來看,一個 Activity

走完 onCreate/onStart/onResume 這幾個生命周期之后,只是完成了應(yīng)用自身的一些配置,比如 window

的一些屬性的設(shè)置/ View 樹的建立(只是建立,并沒有顯示,也就是說只是調(diào)用了 inflate 而已) . 后面 ViewRootImpl

還會調(diào)用兩次performTraversals ,初始化 Egl 以及 measure/layout/draw. 等.

所以我們定義一個 Android 應(yīng)用的啟動時間, 肯定不能在 Activity 的回調(diào)函數(shù)上下手.而是以用戶在手機屏幕上看到你在 onCreate 的 setContentView 中設(shè)置的 layout 完全顯示為準(zhǔn),也就是我們常說的應(yīng)用第一幀.

上面扯得有點遠(yuǎn),不感興趣的話可以不看,下面直接說方法.

題主說的 adb shell am start -w packagename/activity,是可以完全應(yīng)用的啟動時間的.不過也要分場景.

1.2 應(yīng)用第一次啟動

也就是我們常說的冷啟動,這時候你的應(yīng)用程序的進(jìn)程是沒有創(chuàng)建的. 這也是大部分應(yīng)用的使用場景.用戶在桌面上點擊你應(yīng)用的 icon 之后,首先要創(chuàng)建進(jìn)程,然后才啟動 MainActivity.

這時候adb shell am start -w packagename/MainActivity 返回的結(jié)果,就是標(biāo)準(zhǔn)的應(yīng)用程序的啟動時間(注意 Android 5.0 之前的手機是沒有 WaitTime 這個值的):

? adb shell am start -W com.media.painter/com.media.painter.PainterMainActivity

Starting:

Intent { act=android.intent.action.MAIN

cat=[android.intent.category.LAUNCHER]

cmp=com.media.painter/.PainterMainActivity }

Status: ok

Activity: com.media.painter/.PainterMainActivity

ThisTime: 355

TotalTime: 355

WaitTime: 365

Complete

8?adb shell am start -W com.media.painter/com.media.painter.PainterMainActivity

Starting:Intent{act=android.intent.action.MAINcat=[android.intent.category.LAUNCHER]cmp=com.media.painter/.PainterMainActivity}

Status:ok

Activity:com.media.painter/.PainterMainActivity

ThisTime:355

TotalTime:355

WaitTime:365

Complete

總共返回了三個結(jié)果,我們以 WaitTime 為準(zhǔn).

關(guān)于ThisTime/TotalTime/WaitTime的區(qū)別,下面是其解釋:

“adb shell am start -W ”的實現(xiàn)在

frameworksbasecmdsamsrccomandroidcommandsamAm.java

文件中。其實就是跨Binder調(diào)用ActivityManagerService.startActivityAndWait()

接口(后面將ActivityManagerService簡稱為AMS),這個接口返回的結(jié)果包含上面打印的ThisTime、TotalTime時間.

startTime記錄的剛準(zhǔn)備調(diào)用startActivityAndWait()的時間點

endTime記錄的是startActivityAndWait()函數(shù)調(diào)用返回的時間點

WaitTime = startActivityAndWait()調(diào)用耗時。

ThisTime、TotalTime 的計算在 frameworksbaseservicescorejavacomandroidserveramActivityRecord.java 文件的 reportLaunchTimeLocked() 函數(shù)中。

我們來解釋下代碼里curTime、displayStartTime、mLaunchStartTime三個時間變量.

curTime表示該函數(shù)調(diào)用的時間點.

displayStartTime表示一連串啟動Activity中的最后一個Activity的啟動時間點.

mLaunchStartTime表示一連串啟動Activity中第一個Activity的啟動時間點.

正常情況下點擊桌面圖標(biāo)只啟動一個有界面的 Activity,此時 displayStartTime 與mLaunchStartTime

便指向同一時間點,此時 ThisTime=TotalTime。另一種情況是點擊桌面圖標(biāo)應(yīng)用會先啟動一個無界面的 Activity

做邏輯處理,接著又啟動一個有界面的Activity,在這種啟動一連串 Activity

的情況下(知乎的啟動就是屬于這種情況),displayStartTime 便指向最后一個 Activity

的開始啟動時間點,mLaunchStartTime 指向第一個無界面Activity的開始啟動時間點,此時

ThisTime!=TotalTime。這兩種情況如下圖:

在上面的圖中,我用①②③分別標(biāo)注了三個時間段,在這三個時間段內(nèi)分別干了什么事呢?

在第①個時間段內(nèi),AMS 創(chuàng)建 ActivityRecord 記錄塊和選擇合理的 Task、將當(dāng)前Resume 的 Activity 進(jìn)行 pause

在第②個時間段內(nèi),啟動進(jìn)程、調(diào)用無界面 Activity 的 onCreate() 等、 pause/finish 無界面的 Activity

在第③個時間段內(nèi),調(diào)用有界面 Activity 的 onCreate、onResume

看到這里應(yīng)該清楚 ThisTime、TotalTime、WaitTime 三個時間的關(guān)系了吧:

WaitTime 就是總的耗時,包括前一個應(yīng)用 Activity pause 的時間和新應(yīng)用啟動的時間;

ThisTime 表示一連串啟動 Activity 的最后一個 Activity 的啟動耗時;

TotalTime 表示新應(yīng)用啟動的耗時,包括新進(jìn)程的啟動和 Activity 的啟動,但不包括前

一個應(yīng)用 Activity pause 的耗時。也就是說,開發(fā)者一般只要關(guān)心 TotalTime 即可,這個時間才是自己應(yīng)用真正啟動的耗時。

Event log中 TAG=am_activity_launch_time 中的兩個值分表表示 ThisTime、TotalTime,跟通過 “adb shell am start -W ” 得到的值是一致的。

最后再說下系統(tǒng)根據(jù)什么來判斷應(yīng)用啟動結(jié)束。我們知道應(yīng)用啟動包括進(jìn)程啟動、走 Activity生命周期 onCreate/onResume

等。在第一次 onResume 時添加窗口到WMS中,然后measure/layout/draw,窗口繪制完成后通知 WMS,WMS

在合適的時機控制界面開始顯示(夾雜了界面切換動畫邏輯)。記住是窗口界面顯示出來后,WMS 才調(diào)用reportLaunchTimeLocked()

通知 AMS Activity 啟動完成。

最后總結(jié)一下,如果只關(guān)心某個應(yīng)用自身啟動耗時,參考TotalTime;如果關(guān)心系統(tǒng)啟動應(yīng)用耗時,參考WaitTime;如果關(guān)心應(yīng)用有界面Activity啟動耗時,參考ThisTime。

1.2 應(yīng)用非第一次啟動

如果是你按Back鍵,并沒有將應(yīng)用進(jìn)程殺掉的話,那么執(zhí)行上述命令就會快一些,因為不用創(chuàng)建進(jìn)程了,只需要啟動一個Activity即可。這也就是我們說的應(yīng)用熱啟動。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

  • Android 自定義View的各種姿勢1 Activity的顯示之ViewRootImpl詳解 Activity...
    passiontim閱讀 179,036評論 25 709
  • 1.什么是Activity?問的不太多,說點有深度的 四大組件之一,一般的,一個用戶交互界面對應(yīng)一個activit...
    JoonyLee閱讀 5,858評論 2 51
  • 【觸發(fā)背景】面對海量APP的今天,APP用戶量和活躍度成為評價一款A(yù)PP是否成功的重要因素。用戶下載APP后,AP...
    siyu8023閱讀 10,630評論 1 14
  • 1.要做一個盡可能流暢的ListView,你平時在工作中如何進(jìn)行優(yōu)化的? ①Item布局,層級越少越好,使用hie...
    fozero閱讀 874評論 0 0
  • 比如《高效能人士的七個習(xí)慣》所說的七個習(xí)慣/原則(最好是背誦英文): 1.Be proactive(積極主動)—個...
    朝夕駿閱讀 472評論 0 0

友情鏈接更多精彩內(nèi)容