Android判斷冷啟動

語言: CN / TW / HK

冷啟動是什麼

冷啟動是一種 Activity 啟動,其中應用程式程序從頭開始響應啟動 Activity 的意圖。 根據App啟動時間文件:

這種型別的啟動在最小化啟動時間方面提出了最大的挑戰,因為系統和應用程式比其他啟動狀態有更多的工作要做。

我們建議始終基於冷啟動的假設進行優化。 這樣做也可以提高溫啟動和熱啟動的效能。

為了優化冷啟動,我們需要對其進行測量,這意味著我們需要監控生產中的冷啟動時間。

傳統方法

如果第一個 Activity 是在應用程式啟動後的一分鐘內建立的,大多數應用程式和庫會報告冷啟動。 它看起來像這樣: ``` class MyApp : Application() {

override fun onCreate() { super.onCreate()

val appCreateMs = SystemClock.uptimeMillis()

var firstActivityCreated = false

registerActivityLifecycleCallbacks(object :
    ActivityLifecycleCallbacks {
  override fun onActivityCreated(
      activity: Activity,
      savedInstanceState: Bundle?
  ) {
    if (firstActivityCreated) {
      return
    }
    firstActivityCreated = true
    val activityCreateMs = SystemClock.uptimeMillis()
    if (activityCreateMs - appCreateMs < 60_000) {
      // TODO Report cold start
    }
  }
})

} } ```

不幸的是,這種方法還包括應用程序開始響應廣播接收器、內容提供者查詢或啟動服務,然後有時在第一分鐘內啟動 Activity 的情況。我們應該將這些情況從冷啟動監控中排除,以避免歪曲我們的結果。

  • 當應用程式程序啟動時,它會呼叫 ActivityThread.main(),它會在 system_server 程序中對 ActivityManagerService.attachApplication() 進行阻塞 IPC 呼叫。

  • system_server 程序對應用程序中的 ActivityThread.bindApplication() 進行 IPC 呼叫,該呼叫將 BIND_APPLICATION 訊息排入主執行緒訊息佇列。

  • 然後,對於需要啟動的每個 Activity ,system_server 程序對應用程序中的 ActivityThread.scheduleTransaction() 進行 IPC 呼叫,將 EXECUTE_TRANSACTION 訊息排入主執行緒訊息佇列。

  • 當對 ActivityManagerService.attachApplication() 的 IPC 呼叫完成後,ActivityThread.main() 然後呼叫 Looper.loop(),它會永遠迴圈,處理髮布到其 MessageQueue 的訊息。

  • 處理的第一條訊息是 BIND_APPLICATION,它呼叫 ActivityThread.handleBindApplication(),後者呼叫 Application.onCreate()。

  • 下一條處理的訊息是 EXECUTE_TRANSACTION,它呼叫 TransactionExecutor.execute() 來啟動活動。

這意味著在 Application.onCreate() 中,主執行緒訊息佇列已經有 EXECUTE_TRANSACTION 訊息入隊。 如果我們從 Application.onCreate() 釋出一條新訊息,它將在 EXECUTE_TRANSACTION 之後執行,因此在建立 Activity 之後。 如果我們釋出一條訊息並且在執行時沒有建立 Activity ,那麼我們就知道這不是冷啟動,即使 Activity 最終在 20 秒後啟動。

以下是我們如何檢測冷啟動: ``` class MyApp : Application() {

override fun onCreate() { super.onCreate()

var firstActivityCreated = false

registerActivityLifecycleCallbacks(object :
    ActivityLifecycleCallbacks {

  override fun onActivityCreated(
      activity: Activity,
      savedInstanceState: Bundle?
  ) {
    if (firstActivityCreated) {
      return
    }
    firstActivityCreated = true
  }
})
Handler().post {
  if (firstActivityCreated) {
    // TODO Report cold start
  }
}

} } ```

溫啟動

根據App啟動時間文件:

有許多潛在的狀態可以被認為是溫啟動。 例如:

使用者退出應用程式,然後重新啟動它。 該過程可能會繼續執行,但應用程式必須通過呼叫 onCreate() 從頭開始重新建立 Activity。

系統從記憶體中殺死應用程式,然後使用者重新啟動它。 程序和 Activity 需要重新啟動,但任務可以從傳遞給 onCreate() 的已儲存例項狀態包中受益。

因此,如果 Activity 是使用儲存的例項狀態包建立的,則不應將其視為冷啟動。 但是,由於程序需要重新啟動,因此除了建立 Activity 之外,還有很多工作要做。 讓我們稱之為一個溫啟動。

我們可以更新我們的程式碼以考慮到這一點: ``` class MyApp : Application() {

override fun onCreate() { super.onCreate()

var firstActivityCreated = false
var hasSavedState = false

registerActivityLifecycleCallbacks(object :
    ActivityLifecycleCallbacks {

  override fun onActivityCreated(
      activity: Activity,
      savedInstanceState: Bundle?
  ) {
    if (firstActivityCreated) {
      return
    }
    firstActivityCreated = true
    hasSavedState = savedInstanceState != null
  }
})
Handler().post {
  if (firstActivityCreated) {
    if (hasSavedState) {
      // TODO Report lukewarm start
    } else {
      // TODO Report cold start
    }
  }
}

} } ```