启动白屏补充
🧩 更准确的时序流程(以 Android 12 为例,简化自 AOSP)
ActivityThread.handleLaunchActivity() 时序:
1. Activity.attach()
⮕ 创建 PhoneWindow,设置 mWindowManager
⮕ 创建 Window 对象(尚未有 DecorView)
2. Activity.performCreate()
⮕ 执行用户代码里的 onCreate()
⮕ 通常调用 setContentView()
⮕ 会触发 PhoneWindow.installDecor()
⮕ 创建 DecorView 并加载布局
3. handleResumeActivity()
⮕ 调用 Activity.performResume()(你的 onResume())
⮕ 然后执行 makeVisible()
⮕ 在这里调用 WindowManager.addView(DecorView)
4. ViewRootImpl.setView() 中:
⮕ 执行 requestLayout()
⮕ 再触发 performTraversals() → 走 View 绘制三部曲
⮕ 第一次 draw() 时,如果 DecorView 没有背景,就会“白屏”
• 窗口对象 早在 attach() 就创建了;
• DecorView 在 setContentView() 才创建;
• addView() 是在 onResume()(即 handleResumeActivity())中执行;
在 DecorView 还没添加到窗口(即未调用 WindowManager.addView())之前,此时“窗口”存在于 WMS(WindowManagerService)中,但还没有任何内容(DecorView)可以展示,所以屏幕上什么都不会显示,一般表现为:
• 如果系统等待 UI 应用的首次绘制 → 屏幕停留在 Launcher;
• 如果是 Android 12+ 并使用了 SplashScreen API → 会显示系统插入的冷启动界面;
• 否则就可能看到 一帧白色背景,由系统或默认 Window 背景撑起 —— 这就是“白屏”。
📦 底层过程拆解:
1. Activity.attach() → PhoneWindow 被赋给 Activity:
• PhoneWindow 创建,但此时 DecorView 还没有被创建;
• WMS 已知道 Activity 对应的 Window 信息,但并不会立即显示窗口。
2. Activity.onCreate() → setContentView():
• 触发 installDecor() 创建 DecorView;
• 但是 并没有立即将 DecorView 添加到 WMS 管理的窗口中,所以还没显示。
3. Activity.onResume() → WindowManager.addView(decor):
• 通过 ViewRootImpl.setView() 注册了窗口内容;
• 此时 WMS 把窗口层级排布好,SurfaceFlinger 开始合成这个 App 的窗口图层;
• 首帧 VSYNC 来临,Choreographer 调度 doFrame() → performTraversals() → 才开始第一次绘制!
🧠 关键点:窗口什么时候被“真正展示”给用户?
1. 创建窗口本身(attach)时并不会展示内容;
2. 展示发生在 DecorView 被添加、并完成一次 draw 后,才会合成到屏幕;
3. 所以:
• 没有 DecorView → 就没有内容可画 → Surface 是空白或透明;
• 如果 WMS 认为你 App 太慢,它可能用 系统级占位背景(白)或者 SplashScreen)填充你这块区域;
• 这就是“启动白屏”的根源。
📌 举个实际例子(Android 12 以下):
• 你没设置冷启动主题(windowBackground);
• Activity 启动后,onCreate() 执行完,才 setContentView();
• 这段时间系统已经在 WMS 中占了这个窗口位置,但没有内容绘制;
• 系统会用默认白色背景渲染 → 所以你看到的是“白屏”。
✅ 结论:
状态 | 是否展示给用户 | 屏幕上显示什么 |
---|---|---|
attach() → onCreate() | ❌ | Launcher 或 SplashActivity 保持显示 |
onCreate() → addView() | ❌ | 尚未合成 Surface |
addView() → 首次 draw() 之前 | ⚠️(可能) | 如果没有背景主题,就白色画布 |
首次 draw() 完成 | ✅ | DecorView 的界面 |