进程的重要性

语言: 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 } } ```