在 Android的启动流程中,系统为了避免「黑屏」并提升启动流畅度,会在真正的 Activity 窗口出现之前,临时插入一种名为 Starting Window(启动占位窗口)的系统窗口。
Starting Window 又细分为两种主要形式:Splash Screen Starting Window 和 Snapshot Starting Window。虽然它们都是“占位窗口”,但产生场景、内容来源、能否自定义以及停留时间都不同。
────────────────
- Splash Screen Starting Window
────────────────
触发时机
• 冷启动(cold start):应用进程尚未存在,或因被系统杀死而重新创建进程时。
• 热启动但无可用快照:例如第一次安装后首次启动,或者系统未能保存上一次界面快照。
内容来源
• 纯系统绘制:背景色、应用图标、可选的品牌图片/动画、圆角以及进入过渡动画等全部由系统根据 Splash Screen API(theme 属性)生成。
可定制项
• 允许开发者通过主题属性(windowSplashScreen* 系列) 或 SplashScreen API 做「品牌化」定制:
- 背景颜色
- 图标或品牌图片
- icon 进入动画 / exit 动画持续时长
- 欲替换为自定义 view(API)
生命周期
• 显示到应用第一个 Activity 完成 onCreate → onResume 并绘制首帧为止(也就是 APP 绘制的第一帧交给 SurfaceFlinger 的那一刻)。
• Splash→首帧之间系统做一个 16ms 左右的交叉淡入淡出(material motion)过渡。
设计目的
• 用统一、品牌化的画面掩盖应用启动的「昂贵阶段」(ClassLoader、Application.onCreate 等)。
• 保持 UI 的一致性和系统级动画体验。
────────────────
2. Snapshot Starting Window
────────────────
触发时机
• 热启动 / 热重回(warm-/hot-start):应用进程仍在,但 Activity 被暂停或停止;用户从 Recents(多任务)或 Launcher 图标重新回到该 Activity 时。
• 系统在该 Activity 上一次可见时成功抓取了 UI 快照(TaskSnapshot)。
内容来源
• 系统曾在 Activity 转入后台时截取的一张屏幕快照(screenshot)。
• 额外可叠加状态栏、导航栏背景保证无缝过渡。
可定制项
• 基本不可定制。它完全复用系统保存的位图;开发者只能通过 setRecentsScreenshotEnabled(false)(API 31+)选择不让系统截屏,但无法改变其样式。
生命周期
• 显示到 Activity 重新 onResume 并绘制出最新一帧为止。
• 如果 UI 几乎无改动,看上去就像瞬间恢复;若 UI 改动较大则用户会看到一次“位图→真实布局”的跳变。
设计目的
• 提供“内容连续性”体验:让用户迅速看到与离开时一模一样的界面,掩盖进程调度、绘制重建或 I/O 等抖动。
• 避免从 Recents 切回来时闪白或出现过度动画断层。
────────────────
3. 核心区别对照
────────────────
• 产生条件
- Splash:应用无以前的快照 / 进程刚启动。
- Snapshot:有快照且进程仍在或可快速冷启。
• 视觉内容
- Splash:品牌化背景 + 图标 + 可选动画。
- Snapshot:上一次真实 UI 的截图。
• 自定义能力
- Splash:高度可定制(Android 12 SplashScreen API)。
- Snapshot:几乎不可定制。
• 用户感知
- Splash:较「品牌化」;往往只有 300-500 ms,有明显 logo-in/out 动画。
- Snapshot:几乎是“静态画面”,看似立即恢复原界面。
• 风险点
- Splash:定制过度会拉长启动耗时。
- Snapshot:如果 UI 改动大、占位图和新 UI 差异会造成“跳帧”感;也存在信息泄露(快照含敏感数据)需通过 FLAG_SECURE 或 setRecentsScreenshotEnabled 处理。
────────────────
一句话总结
Splash Screen Starting Window 用“品牌页”遮住冷启动的黑屏;Snapshot Starting Window 用“上次的截图”遮住热启动的空挡。两者都是系统插入的 TYPE_APPLICATION_STARTING 窗口,但场景与可定制程度截然不同。