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,展示真实内容

|

当前网速较慢或者你使用的浏览器不支持博客特定功能,请尝试刷新或换用Chrome、Firefox等现代浏览器