3. 启动窗口背景与主题切换优化
为什么冷启动会先看到白屏或黑屏
Android 冷启动时,系统在应用进程尚未创建、Activity 尚未完成首帧绘制之前,会先显示一个「启动窗口」(Starting Window)。这个窗口的默认背景来自应用主题中的 windowBackground。如果主题是浅色,用户看到白屏;如果是深色,用户看到黑屏。它并不是应用真正绘制出来的界面,而是系统用主题背景临时填充的占位画面。
因此,消除白屏/黑屏的关键不是「加快首帧」,而是让这个占位窗口在视觉上与真实首屏一致,使启动过程看起来是「无缝」的。下面这张图展示了启动窗口背景从主题取值到用户感知的完整链路。
配置启动窗口背景的两种方式
方式一:直接修改主题的 windowBackground,让它与首屏背景一致。这是最简单、最稳定的做法,适合首屏背景为纯色或简单渐变的场景。
<style name="AppTheme.Launch" parent="Theme.AppCompat.Light.NoActionBar">
<item name="android:windowBackground">@drawable/launch_bg</item>
<item name="android:windowFullscreen">true</item>
</style>
其中 launch_bg 可以用 layer-list 定义,把品牌色、Logo 或渐变放在启动窗口上:
<layer-list xmlns:android="http://schemas.android.com/apk/res/android">
<item>
<shape android:shape="rectangle">
<gradient
android:startColor="#1A73E8"
android:endColor="#0D47A1"
android:angle="270"/>
</shape>
</item>
<item android:gravity="center">
<bitmap android:src="@drawable/ic_launcher_foreground"
android:gravity="center"/>
</item>
</layer-list>
方式二:使用 windowDisablePreview 关闭预览窗口。这会让系统不显示启动窗口,但代价是用户点击图标后可能短暂无响应,体验反而更差,一般不推荐单独使用。
注意:不要为了「消除白屏」而把 windowBackground 设为透明或 null。透明背景会让桌面壁纸透出来,视觉上更混乱;设为 null 则可能触发系统默认黑屏。正确做法是让启动窗口背景与首屏背景一致。
验证窗口背景对感知启动速度的改善
验证方法不是看冷启动耗时是否下降,而是看「视觉连续性」是否改善。可以用高速相机或屏幕录制逐帧检查:从点击图标到首帧出现之间,是否存在与首屏明显不同的颜色块。
| 检查项 | 优化前 | 优化后 | 判断标准 |
|---|---|---|---|
| 启动窗口背景色 | 纯白 #FFFFFF | 与首屏一致 #1A73E8 | 颜色差 ΔE < 3 |
| 首帧出现前画面 | 白屏持续 300~800ms | 品牌色渐变 + Logo | 无突兀色块切换 |
| 用户主观评分 | 「卡了一下」 | 「挺快的」 | 主观评分提升 ≥ 1 分 |
| 冷启动耗时 | 1200ms | 1200ms(不变) | 耗时不是本优化目标 |
关键认知:启动窗口背景优化不改变真实启动耗时,它改变的是用户对耗时的「感知」。当占位画面与真实首屏视觉一致时,用户会把整个启动过程感知为一个连续的品牌展示,而不是「白屏 + 突然出现内容」的割裂体验。
实操:为现有应用配置启动窗口背景
- 在
res/drawable/下新建launch_bg.xml,用layer-list定义与首屏一致的背景(纯色、渐变或带 Logo)。 - 在
res/values/themes.xml中新建AppTheme.Launch,设置android:windowBackground指向@drawable/launch_bg。 - 在
AndroidManifest.xml中把启动 Activity 的android:theme设为@style/AppTheme.Launch。 - 在启动 Activity 的
onCreate()中,首帧绘制完成后调用setTheme(R.style.AppTheme)切回正常主题,避免启动主题影响后续界面。 - 用屏幕录制逐帧检查:点击图标后第一帧是否已经是品牌色背景,而不是白色或黑色。
// 启动 Activity 中切回正常主题
@Override
protected void onCreate(Bundle savedInstanceState) {
setTheme(R.style.AppTheme); // 必须在 super.onCreate 之前
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
}
完成上述配置后,冷启动过程中用户看到的第一帧就是品牌色背景,首帧渲染完成后自然过渡到真实界面,白屏或黑屏现象消失。此时再用高速相机验证,应观察到从点击到首帧之间没有与首屏明显不同的颜色块。