Android应用启动

72 阅读5分钟

应用启动

用户希望应用能够快速加载并及时响应。启动时间过长的应用无法满足这个期望,并且可能会令用户失望。这种糟糕的体验可能会导致用户在 Play 商店针对您的应用给出很低的评分,甚至完全抛弃您的应用。

本页面提供了有助于优化应用启动时间的信息,包括启动流程的内部机制概述、如何分析启动性能,以及一些常见的启动时间问题和有关如何解决这些问题的提示。

了解不同的应用启动状态

应用有三种启动状态:冷启动、温启动或热启动。每种状态都会影响应用向用户显示所需的时间。在冷启动中,应用从头开始启动。在另外两种状态中,系统需要将后台运行的应用带入前台。

我们建议您始终在假定冷启动的基础上进行优化。这样做也可以提升温启动和热启动的性能。

如需优化应用以实现快速启动,了解系统和应用层面的情况以及它们在各个状态中的互动方式很有帮助。

确定应用启动时间的两个重要指标是初步显示所用时间 (TTID) 和完全绘制所用时间 (TTFD)。TTID 是显示第一帧所用的时间,TTFD 则是应用达到可全面互动的状态所用的时间。两者同样重要,因为 TTID 让用户知道应用正在加载,TTFD 表示用户等待多长时间才能实际使用应用。如果其中任一时间过长,用户都可能会在应用完全加载之前退出应用。

冷启动

冷启动是指应用从头开始启动。这意味着,系统进程在冷启动后才创建应用进程。发生冷启动的情况包括应用自设备启动后或系统终止应用后首次启动。

这种启动给最大限度地减少启动时间带来了最大的挑战,因为系统和应用要做的工作比在其他启动状态下更多。

在冷启动开始时,系统有以下三项任务:

  1. 加载并启动应用。
  2. 在启动后立即显示应用的空白启动窗口。
  3. 创建应用进程

系统一创建应用进程,应用进程就负责后续阶段:

  1. 创建应用对象。
  2. 启动主线程。
  3. 创建主 activity。
  4. 膨胀视图。
  5. 创建屏幕布局。
  6. 执行初步绘制。

当应用进程完成第一次绘制时,系统进程就会换掉显示的后台窗口,将其替换为主 activity。此时,用户可以开始使用应用。

图 1 显示系统进程和应用进程之间如何交接工作。(绿色、橙色)

**图 1.**  以可视化方式呈现应用冷启动的重要部分。

在创建应用和创建 activity 的过程中可能会出现性能问题。

应用创建

当应用启动时,空白启动窗口将保留在屏幕上,直到系统首次完成应用绘制。此时,系统进程会切换应用的启动窗口,让用户与应用互动。

如果您在自己的应用中替换了 Application.onCreate(),系统将对应用对象调用 onCreate() 方法之后,应用生成主线程(也称为界面线程),并用其执行创建主 activity 的任务。**

从此时开始,系统级和应用级进程根据应用生命周期阶段继续运行。

activity 创建

在应用进程创建 activity 后,activity 将执行以下操作:

  1. 初始化值。
  2. 调用构造函数。
  3. 根据 activity 的当前生命周期状态,相应地调用回调方法,如 Activity.onCreate()

通常,onCreate() 方法对加载时间的影响最大,因为它执行工作的开销最高:加载和膨胀视图,以及初始化运行 activity 所需的对象。

温启动

温启动包含了在冷启动期间发生的部分操作。同时,它的开销要比热启动高。有许多潜在状态可视为温启动,例如以下状态:

  • 用户在退出应用后又重新启动应用。进程可能继续运行,但应用必须通过调用 onCreate() 从头开始重新创建 activity。
  • 系统将您的应用从内存中逐出,然后用户又重新启动它。进程和 activity 需要重启,但传递到 onCreate() 的已保存实例 state bundle (移动端的一个状态保存。例如Flutter restorationScopeId、restorationId 组件属性可以保存)对于完成此任务有一定助益。

热启动

应用的热启动开销比冷启动更低。在热启动中,系统会将您的 activity 带到前台。如果应用的所有 activity 仍驻留在内存中,则应用可以避免重复执行对象初始化、布局膨胀和呈现。

但是,如果一些内存为响应内存整理事件(如 onTrimMemory())而被完全清除,则需要为了响应热启动事件而重新创建相应的对象。

热启动显示的屏幕上行为和冷启动场景相同。在应用完成 activity 呈现之前,系统进程将显示空白屏幕。

图 2.  包含各种启动状态及其各自进程的示意图,其中每个状态都将从绘制的第一帧开始