程序的重要性

語言: CN / TW / HK

如果我們 post 一條訊息並且在該訊息執行時沒有建立任何 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
  }
}

} } ```

使用這種方法,我們必須等待 Activity 啟動或訊息執行,然後才能知道應用程式啟動是否是冷啟動。 有時從 Application.onCreate() 中知道這一點會很有用。 例如,我們可能希望非同步預載入資源以優化冷啟動: ``` class MyApp : Application() {

override fun onCreate() { super.onCreate()

if (isColdStart()) {
  preloadDataForUiAsync()
}

} } ```

程序重要性

雖然沒有 Android API 可以知道程序為什麼啟動,但有一個 API 可以知道程序為什麼仍在執行:RunningAppProcessInfo.importance,我們可以從 ActivityManager.getMyMemoryState() 中讀取。 根據程序和應用程式生命週期文件:

為了確定哪些程序在記憶體不足時應該被殺死,Android 根據其中執行的元件和這些元件的狀態將每個程序置於“重要性層次結構”中。 在決定如何對程序進行分類時,系統將根據在流程中當前 Activity 的所有元件中找到的最重要級別做出決定。

當程序開始時,我們可以檢查它的重要性。 如果重要性為 IMPORTANCE_FOREGROUND,則必須是冷啟動: ``` class MyApp : Application() {

override fun onCreate() { super.onCreate()

if (isForegroundProcess()) {
  preloadDataForUiAsync()
}

}

private fun isForegroundProcess(): Boolean { val processInfo = ActivityManager.RunningAppProcessInfo() ActivityManager.getMyMemoryState(processInfo) return processInfo.importance == IMPORTANCE_FOREGROUND } } ```

用資料確認

我在示例應用程式中使用這兩種方法實現了冷啟動檢測,並獲得了相同的結果。 然後,我將檢測程式碼新增到具有足夠安裝量的生產應用程式中,以提供有意義的結果。

  • 當啟動重要性為 100 時,總會在第一次 post 之前建立一個 Activity 。 當一個 Activity 在第一次 post 之前建立時,97.4% 的時間重要性為 100。

  • 當啟動重要性為 400 時,幾乎不會在第一次 post 之前建立 Activity。 幾乎從不也不是從不,仍然有足夠多的案例在首次 post 之前建立 Activity ,2.4% 的時間重要性為 400。

對重要性為 400 的 2.4% 最可能的解釋是那些不是冷啟動,但是系統幾乎在程序開始後立即收到啟動 Activity 的查詢,就在執行 Application.onCreate() 時,但在我們有機會發布我們第一個post。

編輯:我在第一次 post 後記錄了重要性,並將其與應用程式啟動時的重要性進行了比較。 我的資料顯示,74% 的應用程式在首次 post 之前建立 Activity 的地方啟動,並且啟動程序重要性不是 100,如果程序重要性在首次釋出後更改為 100。 這似乎證實了系統決定在應用程式已經開始啟動後啟動 Activity 的理論。

結論

我們可以結合上一篇文章的發現來準確確定冷啟動。 冷啟動:

  • 在應用程式啟動時程序重要性為 IMPORTANCE_FOREGROUND。

  • 在第一個 post 出隊之前建立了第一個 Activity 。

  • 具有使用空包建立的第一個 Activity 。

這是更新後的程式碼: ``` class MyApp : Application() {

override fun onCreate() { super.onCreate()

if (isForegroundProcess()) {
  var firstPostEnqueued = true
  Handler().post {
    firstPostEnqueued = false
  }
  registerActivityLifecycleCallbacks(object :
      ActivityLifecycleCallbacks {

    override fun onActivityCreated(
        activity: Activity,
        savedInstanceState: Bundle?
    ) {
      unregisterActivityLifecycleCallbacks(this)
      if (firstPostEnqueued && savedInstanceState == null) {
        // TODO Report cold start
      }
    }
  })
}

}

private fun isForegroundProcess(): Boolean { val processInfo = ActivityManager.RunningAppProcessInfo() ActivityManager.getMyMemoryState(processInfo) return processInfo.importance == IMPORTANCE_FOREGROUND } } ```