在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

吃透冷/热/温启动的机制差异、建立"冷启动预加载 + 热启动状态恢复"双轨优化、理性评估保活策略的成本收益


一、前置思考:启动优化必须先"分类"

1.1 启动不是一件事,是三件事

启动类型 触发条件 特征 优化重点
冷启动 进程被杀后重新打开 最慢,全链路 预加载/并行
热启动 退后台立即回来 快,进程存活 状态恢复
温启动 退后台一段时间 中,部分回收 缓存预热

核心认知:不同启动类型的问题完全不同——冷启动的问题是"太慢",
热启动的问题是"状态丢失/恢复错乱"。用一套方案解决两类问题,必然顾此失彼。

1.2 启动类型的占比分布

典型 App 启动分布:
  冷启动 35% (进程被回收)
  温启动 30% (后台一段时间)
  热启动 35% (快速切换)

策略含义

  • 冷启动优化覆盖 35% 场景(但单次收益最大);
  • 热启动优化覆盖 35% 场景(用户感知最直接);
  • 两者都要做,但投入应分开评估

1.3 差异化优化的总原则

原则 说明
冷启动做"减法" 预加载路径、并行、少做
热启动做"恢复" 缓存状态、页面保活、秒回
保活做"权衡" 保活成本 vs 冷启动优化收益
目标统一 用户感知的"回到 App"都够快

二、核心原理:三态启动机制

2.1 冷启动完整路径

点击图标 → 进程创建 → 类加载 → Application初始化
→ Ability创建 → loadContent → 首帧 → 数据加载 → 可交互
         ↑ 全过程最重, 无任何缓存可依赖

冷启动的耗时大头:

  1. 进程创建 + 类加载(系统+框架固定开销);
  2. 初始化任务(SDK/DB/缓存,可并行优化);
  3. 首帧渲染(布局/资源);
  4. 首屏数据(网络/缓存)。

2.2 热启动路径

点击图标 → 进程已存活 → 窗口恢复 → 页面状态还原 → 秒回
         ↑ 无进程创建, 无类加载, 无初始化

热启动的核心矛盾:

  1. 状态丢失:页面滚动位置/表单输入/数据上下文;
  2. 窗口重建:onWindowStageCreate 重新触发;
  3. 后台任务残留:之前的网络/任务还在跑,与新状态冲突。

2.3 温启动路径

点击图标 → 进程存活但页面栈已回收 → 重建页面
         ↑ 部分缓存可用(Application 还在), 页面级重建

温启动优化重点:页面级缓存恢复(页面数据快照、图片缓存仍在)。


三、源码/API 深度解析:差异化方案

3.1 冷启动预加载路径(Preload Path)

冷启动的核心是把"必做"提前并行:

// 冷启动预加载: 在 Application 阶段并行预热
export default class MyApplication extends AbilityApplication {
  onCreate(): void {
    // 1. 关键配置立即读取(Preferences 同步, 毫秒级)
    const cfg = prefs.getSync('app_cfg');

    // 2. 重任务异步预热(不阻塞首帧)
    this.preloadWarmUp();
  }

  private preloadWarmUp(): void {
    // 并行预热: DB 打开 + 网络预连接 + 图片缓存
    const tasks = [
      new taskpool.Task(warmUpDb),
      new taskpool.Task(preConnectApi),
      new taskpool.Task(warmUpImageCache)
    ];
    taskpool.execute(tasks);   // 全部后台, 首帧无感
  }
}

预加载纪律

  • 只预热首屏 100% 会用的资源;
  • 预热任务全部后台,绝不阻塞首帧;
  • 预热结果要有缓存承接(避免重复加载)。

3.2 热启动状态恢复

热启动必须恢复用户离开时的状态

// 热启动状态恢复: 保存/恢复关键状态
export class StateKeeper {
  private static saved: Map<string, string> = new Map();

  // 页面隐藏时保存状态
  static save(key: string, state: string): void {
    this.saved.set(key, state);
  }

  // 恢复时优先用缓存状态
  static restore(key: string): string | undefined {
    return this.saved.get(key);
  }
}

// 页面: 状态保存与恢复
onPageHide(): void {
  // 保存滚动位置/表单/列表状态
  StateKeeper.save('home_scroll', String(this.list.offset()));
  StateKeeper.save('home_filters', JSON.stringify(this.filters));
}
onPageShow(): void {
  const scroll = StateKeeper.restore('home_scroll');
  if (scroll !== undefined) {
    this.list.scrollTo({ offset: Number(scroll) });
  }
}

恢复原则

  1. 恢复优先于重新加载:有缓存状态直接回,不闪加载;
  2. 数据增量刷新:状态恢复后再静默刷新增量;
  3. 避免双重加载:恢复态与网络态要有状态机协调。

3.3 AppTaskManager:后台任务管理

AppTaskManager 管理应用任务(页面栈)状态,影响热启动体验:

import { appTaskManager } from '@kit.AbilityKit';

// 查询任务状态
const isBackground = appTaskManager.isBackground();

// 任务切换监控: 前台/后台切换时调整策略
appTaskManager.on('taskStateChanged', (info) => {
  if (info.isBackground) {
    // 进后台: 降耗 + 保存状态 + 暂停非必要任务
  } else {
    // 回前台: 恢复状态 + 增量刷新 + 提速
  }
});

3.4 保活策略权衡

保活(Keep-Alive)与冷启动优化是两条路线

路线A: 保活 → 尽量减少冷启动发生
  成本: 后台耗电/占用资源/系统限制风险
路线B: 冷启动优化 → 让每次冷启动都很快
  成本: 开发投入, 无后台负担
维度 保活路线 冷启动优化路线
后台成本 高(耗电/内存)
系统风险 被限制/被清理
用户体验 取决于保活成功率 稳定可预期
长期价值 低(系统会收紧) 高(永久收益)

结论不要过度追求保活。合规的轻量保活(如 JobScheduler 低频任务)
可以提升热启动比例,但主投入应放在冷启动优化——这是可掌控的收益。

3.5 启动模式配置

// module.json5 启动相关配置
{
  "module": {
    "name": "entry",
    "type": "entry",
    "launchType": "singleton",     // 单实例: 避免多实例开销
    "ability": [
      {
        "name": "EntryAbility",
        "launchType": "singleton", // singleton/standard
        "startWindowIcon": "$media:start_icon",
        "startWindowBackground": "$color:start_bg"
      }
    ]
  }
}
配置 作用
launchType: singleton 单实例,重复打开走 onNewWant
startWindowIcon 启动窗口图标(首帧前展示)
startWindowBackground 启动窗口背景色(防白屏)

四、企业级实战:双轨优化方案

4.1 冷启动预加载清单

优先级 预加载项 时机
P0 首屏数据缓存 Application 阶段
P0 数据库连接 后台预热
P1 网络预连接 后台预热
P1 图片缓存预热 后台预热
P2 次要模块 首帧后延迟

4.2 热启动恢复清单

恢复项 手段
页面栈位置 保存/恢复滚动位置
表单输入 草稿保存/恢复
列表数据 内存缓存直显
筛选条件 状态快照恢复
视频播放位 播放进度保存

4.3 差异化优化对照表

场景 冷启动策略 热启动策略
数据 缓存优先 + 并行预取 状态恢复 + 增量刷新
页面 骨架屏 + 渐进 直接显示缓存快照
网络 预连接 + 批处理 复用连接 + 增量
图片 预热首屏 内存缓存直显
动画 首屏不播动画 保留状态过渡

4.4 启动体验节奏设计

冷启动: 品牌屏 → 骨架屏 → 缓存内容 → 网络增量 (渐进)
热启动: 缓存快照直显 → 静默刷新 (秒回)
温启动: 缓存直显 → 懒加载重建 (亚秒)

五、排查与优化:启动耗时分布

5.1 启动耗时拆解

阶段 冷启动 热启动
进程创建 200ms 0ms
初始化 300ms 0ms
页面构建 200ms 100ms
数据加载 400ms 50ms(缓存)
首帧 150ms 50ms
合计 1.25s 200ms

5.2 高频坑点速查

  • 是否区分了冷/热启动做了差异化处理?
  • 冷启动是否在 Application 阶段并行预热?
  • 预热是否阻塞了首帧(应该全部后台)?
  • 热启动是否恢复了滚动/表单/列表状态?
  • 恢复后是否静默增量刷新(而非重新加载)?
  • 是否配置了 startWindowIcon 防白屏?
  • launchType 是否合理(singleton 为主)?
  • 保活策略是否过度(后台耗电风险)?
  • 温启动是否有页面级缓存恢复?
  • 启动耗时是否分别统计冷/热口径?

六、总结与进阶

6.1 收益模型(参考实测)

指标 优化前 优化后 提升
冷启动 TTI 2.8s 1.2s -57%
热启动恢复 1.1s(重载) 0.2s(缓存) -82%
温启动 1.8s 0.6s -67%
状态丢失率 40% 5% 87%

6.2 工程规范

  1. 双轨设计:冷启动预加载与热启动恢复分别设计;
  2. 状态保存标准化:页面统一 onPageHide 保存状态;
  3. 预热白名单:预加载项评审制(防过度);
  4. 保活评审:保活方案需过功耗评估(第 34 篇联动);
  5. 分口径监控:冷/热启动耗时分别入大盘(第 41 篇联动)。

6.3 进阶方向

  • 启动场景识别:自动识别冷/热/温并上报;
  • 缓存分层恢复:内存/磁盘快照分级恢复;
  • 页面保活粒度:关键页面 vs 普通页面差异保活;
  • 启动与功耗平衡:预热任务与省电策略协同(第 34 篇联动)。

附:Demo 演示说明

Tab 演示内容
🌡️ 启动类型 冷/热/温三态启动对比(触发条件/特征/耗时)
🧊 冷启动优化 冷启动预加载路径演示(Application 并行预热)
🔥 热启动优化 状态保存/恢复演示(滚动位置/表单/列表)
💤 保活权衡 保活 vs 冷启动优化两条路线成本收益对比
📊 耗时分布 冷/热启动各阶段耗时对比 + 优化前后数据
Logo

作为“人工智能6S店”的官方数字引擎,为AI开发者与企业提供一个覆盖软硬件全栈、一站式门户。

更多推荐