移动应用中的热启动:是什么、因素以及如何加速

作者: IT Sectr 发布日期: 2026-03-31 阅读时间: 10 分钟

Hot Start — 是从最小化状态启动移动应用,此时进程已存在于内存中。与冷启动不同的是,系统在冷启动时会从头创建进程,而热启动仅需 200 到 500 毫秒,并且只调用 Activity 中的 onCreateonStart 方法。根据 Android Developers, 2025,热启动是最快的场景,但其速度直接取决于生命周期方法中的工作量。

要点

  • 热启动 — 启动已在内存中且未被系统销毁的应用。
  • 冷启动 — 完整启动并创建进程,耗时 2–5 秒。
  • 温启动 — 部分重启,Activity 被重新创建但进程仍然存活。
  • onCreateonStart — 热启动时唯一调用的方法。
  • 优化 热启动 可减少感知启动时间并改善用户体验。

移动应用中的热启动是什么

热启动 — 是一种应用启动场景,其进程已存在于设备的 RAM 内存中。用户最小化应用,然后返回 — 系统不创建新进程,而是恢复现有进程。在此场景中,无需加载操作系统、初始化 Application 类和创建进程,从而大幅缩短 UI 出现在屏幕上的时间。根据 Android 文档(2025 年),热启动仅需 200–500 毫秒,而冷启动可能达到 5 秒或更长。速度差异在内存有限的设备上尤为明显,系统更频繁地卸载后台应用。

热启动的主要特点 — 最少的生命周期方法调用集。在 Android 中为 Activity.onCreateActivity.onStart,在 iOS 中为 applicationDidBecomeActive。与冷启动不同,冷启动会依次调用 Application.onCreate、ContentProvider.onCreate、Activity.onCreate 和大量库初始化,而热启动会跳过所有这些阶段。开发人员必须了解在热启动时具体执行哪些代码 — 通常 SDK、分析和 DI 容器的繁重初始化在冷启动和热启动时都会重复执行,尽管在热启动时已不再需要它们。

冷启动、温启动和热启动:对比

三种应用启动场景在初始化深度上有所不同。冷启动发生在应用首次安装后、设备重启或从内存卸载后启动时。系统创建新的 Linux 进程,加载 Application 类,创建 ContentProvider 实例,执行库初始化,然后才显示 Activity。整个过程耗时 2–10 秒,具体取决于应用的复杂性和设备特性。

温启动 — 中间场景。应用进程在内存中存活,但 Activity 已被销毁且必须重新创建。例如,当屏幕旋转或从其他应用返回时,Activity 因内存不足而被卸载,但进程仍保留。温启动包括调用 Activity.onCreateActivity.onStart,但不包括 Application.onCreate 和 ContentProvider 初始化。温启动时间 — 500 毫秒到 2 秒。热启动 — 三者中最快:Activity 已存在于返回栈中,进程存活,系统只需调用 Activity.onRestartonStartonResume。热启动时间 — 200–500 毫秒。与温启动的区别在于 Activity 不是重新创建 — 而是从现有实例恢复。

参数冷启动温启动热启动
进程重新创建存在存在
Activity重新创建重新创建恢复
Application.onCreate调用不调用不调用
典型时间2–10 秒0.5–2 秒0.2–0.5 秒
生命周期方法全部onCreate + onStartonRestart + onStart

热启动时的 Android 生命周期

在 Android 中,当用户通过最近应用屏幕或点击最小化状态的图标返回应用时,热启动 被触发。系统检查进程是否存活,如果是 — 依次调用 Activity.onRestartonStartonResume。热启动时不调用 onCreate 方法,因为 Activity 实例已存在于内存中。这是与温启动的重要区别,温启动中由于 Activity 被销毁,onCreate 仍会被调用。根据 Google I/O 2019 的数据,Android 中典型的热启动时间为 200–400 毫秒,此阶段的任何延迟都会直接增加感知启动时间。

开发人员经常没有注意到,UI 初始化、LiveData 订阅或 RecyclerView 配置的代码不仅在 onCreate 中执行,也在 onStart 或 onResume 中执行。热启动时,这些代码块会再次执行,即使 UI 已经配置完成。建议将一次性初始化(在 onCreate 中检查 savedInstanceState)和可恢复逻辑(onStart/onResume)分开。例如,繁重操作 — 配置适配器、加载列表 — 最好移到不在 onRestart 时执行的块中,或检查 savedInstanceState。

跟踪启动类型的示例

以下 Kotlin 代码演示了一种确定启动场景并测量时间的简单方法。launchTimeStamp 变量记录启动开始的时刻,isColdStart 允许区分冷启动和热启动的逻辑。

kotlin
class MainActivity : AppCompatActivity() {

    private var launchTimeStamp = 0L
    private var isColdStart = true

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_main)

        if (savedInstanceState == null) {
            isColdStart = true
            launchTimeStamp = System.currentTimeMillis()
            // 一次性初始化
        } else {
            isColdStart = false
            // 热启动 — Activity 被恢复
        }
    }

    override fun onResume() {
        super.onResume()
        if (isColdStart) {
            val launchTime =
                System.currentTimeMillis() - launchTimeStamp
            Log.d("LaunchTime", "冷启动:$launchTime 毫秒")
        }
    }
}

热启动时的 iOS 生命周期

在 iOS 中,热启动 对应应用通过 sceneDidBecomeActive(UIKit)或 onAppear(SwiftUI)从后台返回。如果应用处于 Suspended 或 Background 状态,操作系统不会重新创建进程。热启动时,AppDelegate 中的 applicationDidBecomeActive 会被调用,但 applicationDidFinishLaunching 不会被调用 — 这类似于 Android 中跳过 Application.onCreate。iOS 更积极地卸载内存中的应用:如果设备 RAM 不足,系统可能卸载后台应用,下一次启动将是冷启动。根据 Apple 开发者文档,iOS 中热启动的平均时间为 300–600 毫秒。

iOS 的关键区别 — 没有与 Android 概念中温启动的直接对应。在 iOS 中,最小化应用时调用 sceneDidEnterBackground,返回时调用 — sceneWillEnterForegroundsceneDidBecomeActive。如果系统卸载场景但保持进程存活,从场景角度看下一次启动是冷启动,但从进程角度看是热启动。开发人员在放置初始化代码时必须考虑到这一点:订阅 NotificationCenter、UI 更新和状态重置应放在 sceneDidBecomeActive 中,而不仅仅是 viewDidLoad 中。

iOS 中处理热启动的示例

这段 Swift 代码展示了如何跟踪热启动次数并分离逻辑。foregroundCount 计数器在每次从后台返回时递增。

swift
class SceneDelegate: UIResponder, UIWindowSceneDelegate {

    var foregroundCount = 0

    func sceneDidBecomeActive(
        _ scene: UIScene
    ) {
        foregroundCount += 1

        if foregroundCount == 1 {
            // 冷启动 — 完全初始化
            setupSDKs()
        } else {
            // 热启动 — 仅更新 UI
            refreshUI()
        }
    }

    private func refreshUI() {
        // 屏幕上的数据更新
    }
}

影响热启动速度的因素

热启动 速度受几类因素影响。第一类 — onStartonResume 生命周期方法中的工作量。如果开发人员在这些方法中放置了网络数据加载、JSON 解析、适配器初始化或繁重计算,每个这样的块都会给启动时间增加数十和数百毫秒。根据 Android Vitals 工具的数据,热启动持续时间超过 800 毫秒的应用在用户再次返回时会流失多达 20% 的用户。

第二类 — 从 savedInstanceState 恢复的 Fragment 和 View。如果 Fragment 包含繁重的 ViewPager2、WebView 或嵌套层次复杂的视图层级,它们的恢复会消耗 CPU 资源。根据 Google I/O 2023 的数据,每个嵌套的 ViewGroup 平均给热启动时的渲染时间增加 2–5 毫秒。第三类 — 第三方 SDK:分析库、崩溃报告、A/B 测试和 DEX 加载器可能在每次从后台返回时执行初始化。建议检查哪些 SDK 在 onStart/onResume 中执行代码,并将非关键任务推迟到后台线程。

热启动的优化方法

热启动 优化的核心是尽量减少恢复生命周期方法中的工作。第一种方法 — 懒初始化:所有不需要用于第一帧 UI 的代码应在 onResume 调用后通过 Handler.postDelayedCoroutine.launch(Dispatchers.IO) 延迟执行。第二种方法 — View 状态缓存:在最小化应用时将数据保存到内存缓存中,这样热启动时就不需要从数据库或网络重新加载。第三种方法 — 在 Android 中使用 SavedStateHandle 和在 iOS 中使用 StateRestorationPolicy 来最小化恢复的数据量。

热启动后的懒加载

在此示例中,Handler.postDelayed 将分析初始化延迟到第一帧渲染后 500 毫秒。这不会影响感知启动时间,因为用户已经看到界面。

kotlin
class AnalyticsDeferrer {

    fun lazyInitAfterHotStart() {
        val handler = Handler(Looper.getMainLooper())
        handler.postDelayed({
            // 第一帧后的初始化
            Analytics.init(Application.getInstance())
            CrashReporter.start()
        }, 500)
    }
}

使用 App Startup 库

AndroidX App Startup 允许管理启动时组件的初始化顺序。所有 ContentProvider 在冷启动时自动初始化,但您可以禁用热启动时不需要的组件的自动初始化。

kotlin
@Initializer(Application::class)
class SdkInitializer : Initializer<Unit> {

    override fun create(context: Context) {
        SdkOne.init(context)
        SdkTwo.init(context)
    }

    override fun dependencies() = emptyList<Class<*>>()
}

启动时间监控工具

测量 热启动 时间既有平台内置的工具,也有第三方解决方案。在 Android 中,关键工具是 Google Play Console 中的 Android Vitals — 它会自动收集所有场景(冷启动、温启动、热启动)的启动时间指标,并按设备型号和操作系统版本进行细分。此外,还可以使用 AndroidX 中的 Macrobenchmark — 一个用于自动化启动性能测试的库。在 iOS 中,对应的是 MetricKit,它收集启动时间、帧率和内存使用情况的数据。

对于热启动的详细分析,Firebase Performance Monitoring(跟踪自定义跟踪)和 New Relic 及其启动时间仪表板都很适合。在开发人员方面,Android 中使用 reportFullyDrawn 进行手动测量 — 这是一个向系统报告 UI 已渲染并准备好交互的确切时刻的 API。在 iOS 中,对应的是 MetricKit 中的 endActivity。结合这些工具,可以确定哪个 SDK 或代码块在特定设备上拖慢了热启动。

用于热启动的 Macrobenchmark 示例

使用 Macrobenchmark 库进行冷启动和热启动测量的 Kotlin 代码。测试启动 Activity 并测量到 complete 状态的时间。

kotlin
@RunWith(AndroidJUnit4::class)
class StartupBenchmark {

    @get:Rule
    val benchmarkRule = MacrobenchmarkRule()

    @Test
    fun hotStart() {
        benchmarkRule.measureRepeated(
            packageName = "com.example.app",
            metrics = listOf(StartupTimingMetric()),
            iterations = 10,
            startupMode = StartupMode.HOT
        ) {
            pressHome()
            startActivityAndWait()
        }
    }
}

常见问题

热启动与冷启动有何不同?

冷启动 从头创建进程 — 加载 Application、ContentProvider,执行所有生命周期方法。热启动使用现有进程,不需要重新创建 Activity,因此快 5–10 倍。

Android 热启动时调用哪些方法?

在 Android 的 热启动 中,依次调用 Activity.onRestartonStartonResumeonCreate 方法不会被调用,因为 Activity 实例已存在于内存中且未被销毁。

为什么热启动可能很慢?

主要原因 — onStartonResume 中的繁重初始化、网络数据加载、复杂 View 层级的恢复以及每次从后台返回时第三方 SDK 代码的执行。

如何测量热启动时间?

在 Android 中使用带有 StartupMode.HOT 的 Macrobenchmark,在 iOS 中使用 MetricKit。生产环境监控适合使用 Firebase Performance 和 Google Play Console 中的 Android Vitals

热启动可以变成温启动吗?

不可以,热启动温启动 — 是由系统确定的不同场景。热启动发生在 Activity 存活时,温启动发生在 Activity 被销毁但进程存活时。开发人员无法强制改变场景。

总结

  • 热启动 — 最快的启动场景(200–500 毫秒),无需创建进程。
  • 冷启动 — 完整启动并创建进程,耗时 2–10 秒。
  • Android 热启动时调用 onRestartonStartonResume,但不调用 onCreate
  • 主要优化方法 — 尽量减少恢复生命周期方法中的工作。
  • MacrobenchmarkAndroid Vitals — 测量和监控热启动的关键工具。
  • 第三方 SDK 和繁重的 View 层级 — 热启动变慢的主要原因。
  • 懒初始化和 View 状态缓存可将感知启动时间减少 30–50%。

我们将开发一款交钥匙移动应用程序

IT Sectr自2017年以来为初创企业和企业打造iOS和Android应用程序。我们将为您提供咨询并提出最佳解决方案。

讨论项目

另请阅读