SplashScreen实现原理-简单版本
系统级 SplashScreen(Android 12+)的实现原理 涉及到以下几个核心系统模块:
• ActivityTaskManagerService(ATMS)和 WindowManagerService(WMS)
• ViewRootImpl 的绘制控制逻辑(mReportNextDraw + finishDrawing())
• SplashScreenView 作为真实系统 View 插入到窗口
• 应用层的 installSplashScreen() 实际上只是连接点,核心控制在系统层
一、SplashScreen 实现原理结构图
App 冷启动
│
├── Launcher 发起 startActivity(Intent)
│
├── ActivityManagerService 创建进程并启动 Activity(MainActivity)
│
├── WindowManagerService:
│ ├── 为该 Activity 创建窗口
│ └── 插入一个“占位窗口” → SplashScreenView
│
├── App 进程调用 MainActivity.onCreate()
│ └── installSplashScreen() 可控制是否延迟消失
│
├── ViewRootImpl 触发首次绘制
│ └── performDraw() → finishDrawing()
│
└── WMS 收到绘制完成 → 自动移除 SplashScreenView → 显示真实界面
二、关键原理详解
1️⃣ 系统创建 SplashScreenView
• 在 ActivityTaskManagerService 创建窗口时,会自动判断是否需要创建 SplashScreen(前提是目标 API ≥ 31 或存在兼容库);
• 然后调用 SplashScreenController#createSplashScreenView();
• 它会创建一个 SplashScreenView,其本质是一个包含背景、图标动画的普通 ViewGroup,临时插入在 App 窗口最顶层;
• 插入后,由系统控制它的移除时机,和 App 无感知。
2️⃣ ViewRootImpl 中绘制触发移除
系统中真正控制 Splash 移除的关键代码在:
ViewRootImpl.java
void draw() {
...
surface.unlockCanvasAndPost(canvas);
if (mReportNextDraw) {
mReportNextDraw = false;
mSurfaceChangedTransactionCallback.run(); // 通知 WMS
mSession.finishDrawing(mWindow); // ✨ 关键:告诉系统我“画完了”
}
}
mReportNextDraw = true 是系统在窗口可见或 resume 时设定的,用于强制绘制第一帧,即使窗口还未 resume。
3️⃣ WMS 移除 SplashScreenView
当系统收到 finishDrawing():
• 如果该窗口曾展示 SplashScreenView;
• 且首次绘制已完成;
• WMS 将自动调用 removeSplashScreenView(),并将真实窗口内容显示出来。
4️⃣ App installSplashScreen() 的作用
在 App 侧调用:
val splashScreen = installSplashScreen()
这实际上是一个桥梁(通过 androidx.core.splashscreen):
• 获取系统设置好的 SplashScreenView;
• 设置过渡动画;
• 设置保留条件 setKeepOnScreenCondition {},使其在真实绘制完成后延迟移除。
但 App 层只是“观察者”,真正的 Splash 是在 WMS 层由系统添加和移除的。
三、源码路径
功能 | 文件路径 |
---|---|
SplashScreenView 构造 | frameworks/base/core/java/com/android/internal/policy/SplashScreenView.java |
控制器入口 | frameworks/base/services/core/java/com/android/server/wm/SplashScreenController.java |
任务添加 Splash | ActivityRecord#createStartingWindow() |
App 报告绘制完毕 | ViewRootImpl#draw() + finishDrawing() |
应用 installSplashScreen | androidx.core:splashscreen 封装(桥接 API) |
四、小结(整体运行逻辑)
阶段 | 内容 |
---|---|
应用启动前 | 系统在窗口层创建并显示 SplashScreenView |
应用 onCreate() 中 | installSplashScreen() 绑定保留条件 |
应用首次绘制 | ViewRootImpl 中调用 finishDrawing() |
条件满足时 | 系统自动移除 Splash,展示真实内容 |
|