进程的重要性

如果我们 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
  }
}
复制代码

猜你喜欢

转载自juejin.im/post/7018498260687912990
今日推荐