Skip to content

SplashScreen API 详解

📚 Android 面试指南 - Jetpack 组件系列

📝 字数:约 10000 字 | ⏱ 建议阅读时间:40 分钟


目录

  1. SplashScreen API 介绍
  2. 替换自定义 Splash Activity
  3. 主题配置
  4. 延迟显示
  5. 图标动画
  6. 深色模式支持
  7. 性能优化
  8. 最佳实践
  9. 常见问题
  10. 面试考点

1. SplashScreen API 介绍

1.1 什么是 SplashScreen API?

SplashScreen API 是 Android 12(API 级别 32)引入的新功能,用于提供一致的品牌化启动体验。

在 Android 12 之前,开发者需要自己实现启动页:

kotlin
// ❌ Android 12 之前的方式
class SplashActivity : AppCompatActivity() {
    
    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_splash)
        
        // 显示自定义 Logo
        // 处理动画
        // 延迟跳转到主页面
        
        // 问题:
        // 1. 系统启动动画和自定义启动页之间有闪屏
        // 2. 不同应用体验不一致
        // 3. 需要处理各种边界情况
    }
}

Android 12 引入了系统级别的启动页,但会导致闪屏问题:

┌─────────────┬──────────────┬──────────────┐
│ 系统启动页  │  自定义启动页  │  主页面       │
│ (强制显示)   │  (Activity 加载) │  (内容)      │
└─────────────┴──────────────┴──────────────┘
        ↓              ↓              ↓
    系统主题        可能不同主题      最终主题
   (可能闪屏)       (可能闪屏)

SplashScreen API 解决了这些问题:

kotlin
// ✅ Android 12+ 使用 SplashScreen API
class MainActivity : AppCompatActivity() {
    
    override fun onCreate(savedInstanceState: Bundle?) {
        // 应用主题中包含 SplashScreen 配置
        // 系统启动页会自动延续到应用加载完成
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_main)
    }
}

1.2 核心特性

特性说明
品牌一致性系统启动页和应用启动页使用相同品牌元素
无缝过渡消除启动过程中的闪屏
深色模式支持自动适配系统主题
延迟控制控制启动页显示时长
图标动画支持 Logo 动画效果
向后兼容通过库支持 Android 5.0+

1.3 添加依赖

kotlin
// build.gradle (Module)
dependencies {
    // SplashScreen 库(向后兼容)
    implementation("androidx.core:core-splashscreen:1.0.1")
}

1.4 工作原理

┌──────────────────────────────────────────────┐
│              应用启动流程                     │
└──────────────────────────────────────────────┘

Android 12+:
┌─────────┬──────────┬──────────┬──────────┐
│ 系统启动│ SplashScreen│ SplashScreen│ 主页面  │
│  动画   │  延续     │  淡出     │  显示   │
└─────────┴──────────┴──────────┴──────────┘
    无闪屏(使用相同的品牌元素)

Android 11 及之前:
┌──────────┬──────────┐
│SplashScreen│ 主页面   │
│ (库实现)  │ 显示     │
└──────────┴──────────┘

2. 替换自定义 Splash Activity

2.1 传统方式的问题

kotlin
// ❌ 传统 Splash Activity
class SplashActivity : AppCompatActivity() {
    
    private lateinit var binding: ActivitySplashBinding
    
    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        binding = ActivitySplashBinding.inflate(layoutInflater)
        setContentView(binding.root)
        
        // 延迟跳转到主页面
        Handler(Looper.getMainLooper()).postDelayed({
            val intent = Intent(this, MainActivity::class.java)
            startActivity(intent)
            finish()
        }, 2000)
    }
    
    // 问题:
    // 1. 额外的 Activity 启动开销
    // 2. 系统启动页和自定义页之间的闪屏
    // 3. 需要处理后台恢复等边界情况
}

2.2 使用 SplashScreen API 替换

步骤 1:修改主题

xml
<!-- res/values/themes.xml -->
<resources>
    <!-- Base application theme -->
    <style name="Theme.MyApp" parent="Theme.MaterialComponents.DayNight">
        <!-- SplashScreen 配置 -->
        <item name="windowSplashScreenBackground">@color/splash_background</item>
        <item name="windowSplashScreenAnimatedIcon">@drawable/splash_logo</item>
        <item name="postSplashScreenTheme">@style/Theme.MyApp</item>
    </style>
    
    <!-- 应用启动时的主题 -->
    <style name="Theme.MyApp.Starting" parent="Theme.SplashScreen">
        <item name="windowSplashScreenBackground">@color/splash_background</item>
        <item name="windowSplashScreenAnimatedIcon">@drawable/splash_logo</item>
        <item name="postSplashScreenTheme">@style/Theme.MyApp</item>
    </style>
</resources>

步骤 2:在 AndroidManifest.xml 中配置

xml
<!-- AndroidManifest.xml -->
<manifest xmlns:android="http://schemas.android.com/apk/res/android">
    
    <application
        android:name=".MyApplication"
        android:theme="@style/Theme.MyApp.Starting">
        
        <!-- 不再需要 SplashActivity -->
        <activity
            android:name=".MainActivity"
            android:exported="true"
            android:theme="@style/Theme.MyApp.Starting">
            <intent-filter>
                <action android:name="android.intent.action.MAIN" />
                <category android:name="android.intent.category.LAUNCHER" />
            </intent-filter>
        </activity>
        
    </application>
</manifest>

步骤 3:移除自定义 SplashActivity

kotlin
// ✅ 删除自定义 SplashActivity
// 直接使用 MainActivity 作为入口

class MainActivity : AppCompatActivity() {
    
    override fun onCreate(savedInstanceState: Bundle?) {
        // SplashScreen 会自动显示,直到应用内容准备就绪
        super.onCreate(savedInstanceState)
        
        // 可以在这里执行初始化,SplashScreen 会保持显示
        performInitialization()
        
        setContentView(R.layout.activity_main)
    }
    
    private fun performInitialization() {
        // 加载用户配置
        // 检查登录状态
        // 准备初始数据
    }
}

2.3 迁移检查清单

kotlin
/**
 * 从自定义 SplashActivity 迁移到 SplashScreen API 的检查清单
 */

// ✅ 1. 添加依赖
// implementation("androidx.core:core-splashscreen:1.0.1")

// ✅ 2. 创建启动主题
// 包含 windowSplashScreen 属性

// ✅ 3. 配置 AndroidManifest
// 设置应用或 Activity 的 theme

// ✅ 4. 移除 SplashActivity
// 从代码中删除

// ✅ 5. 更新 Manifest
// 移除 SplashActivity 的声明

// ✅ 6. 处理初始化逻辑
// 将 SplashActivity 中的逻辑移到合适的位置

// ✅ 7. 测试
// 冷启动、热启动、配置变化等场景

3. 主题配置

3.1 基本主题属性

xml
<!-- res/values/themes.xml -->
<resources>
    
    <!-- SplashScreen 启动主题 -->
    <style name="Theme.App.Starting" parent="Theme.SplashScreen">
        
        <!-- 背景颜色 -->
        <item name="windowSplashScreenBackground">@color/primary_brand</item>
        
        <!-- 图标(Android 12+ 支持动画) -->
        <item name="windowSplashScreenAnimatedIcon">@drawable/app_logo</item>
        
        <!-- 图标背景(圆形) -->
        <item name="windowSplashScreenIconBackgroundColor">@color/icon_background</item>
        
        <!-- SplashScreen 消失后应用的主题 -->
        <item name="postSplashScreenTheme">@style/Theme.App</item>
        
    </style>
    
    <!-- 应用主主题 -->
    <style name="Theme.App" parent="Theme.MaterialComponents.DayNight.NoActionBar">
        <item name="colorPrimary">@color/primary_brand</item>
        <item name="colorPrimaryVariant">@color/primary_dark</item>
        <item name="colorOnPrimary">@color/white</item>
        <item name="colorSecondary">@color/secondary_brand</item>
        <!-- 其他主题属性 -->
    </style>
    
</resources>

3.2 深色模式主题

xml
<!-- res/values/themes.xml (浅色模式) -->
<resources>
    <style name="Theme.App.Starting" parent="Theme.SplashScreen">
        <item name="windowSplashScreenBackground">@color/white</item>
        <item name="windowSplashScreenAnimatedIcon">@drawable/logo_dark</item>
        <item name="windowSplashScreenIconBackgroundColor">@color/transparent</item>
        <item name="postSplashScreenTheme">@style/Theme.App.Light</item>
    </style>
</resources>

<!-- res/values-night/themes.xml (深色模式) -->
<resources>
    <style name="Theme.App.Starting" parent="Theme.SplashScreen">
        <item name="windowSplashScreenBackground">@color/black</item>
        <item name="windowSplashScreenAnimatedIcon">@drawable/logo_light</item>
        <item name="windowSplashScreenIconBackgroundColor">@color/transparent</item>
        <item name="postSplashScreenTheme">@style/Theme.App.Dark</item>
    </style>
</resources>

3.3 多主题支持

xml
<!-- res/values/themes.xml -->
<resources>
    
    <!-- 默认主题 -->
    <style name="Theme.App.Starting" parent="Theme.SplashScreen">
        <item name="windowSplashScreenBackground">@color/splash_blue</item>
        <item name="windowSplashScreenAnimatedIcon">@drawable/logo_blue</item>
        <item name="postSplashScreenTheme">@style/Theme.App.Blue</item>
    </style>
    
    <!-- 节日主题 -->
    <style name="Theme.App.Starting.Christmas" parent="Theme.SplashScreen">
        <item name="windowSplashScreenBackground">@color/christmas_red</item>
        <item name="windowSplashScreenAnimatedIcon">@drawable/logo_christmas</item>
        <item name="postSplashScreenTheme">@style/Theme.App.Christmas</item>
    </style>
    
    <!-- 活动主题 -->
    <style name="Theme.App.Starting.Sale" parent="Theme.SplashScreen">
        <item name="windowSplashScreenBackground">@color/sale_yellow</item>
        <item name="windowSplashScreenAnimatedIcon">@drawable/logo_sale</item>
        <item name="postSplashScreenTheme">@style/Theme.App.Sale</item>
    </style>
    
</resources>

3.4 Kotlin 代码中选择主题

kotlin
class MyApplication : Application() {
    
    override fun onCreate() {
        super.onCreate()
        
        // 根据条件选择主题
        val isChristmas = isChristmasSeason()
        val isSalePeriod = isSalePeriod()
        
        // 注意:主题通常在 Manifest 中静态配置
        // 动态切换需要在 Activity 级别处理
    }
}

// 在 Activity 中动态应用主题
class MainActivity : AppCompatActivity() {
    
    override fun attachBaseContext(newBase: Context) {
        // 在 onCreate 之前执行
        val theme = when {
            isChristmasSeason() -> R.style.Theme_App_Starting_Christmas
            isSalePeriod() -> R.style.Theme_App_Starting_Sale
            else -> R.style.Theme_App_Starting
        }
        val context = ContextThemeWrapper(newBase, theme)
        super.attachBaseContext(context)
    }
    
    private fun isChristmasSeason(): Boolean {
        val calendar = Calendar.getInstance()
        return calendar.month == Calendar.DECEMBER && calendar.dayOfMonth in 20..31
    }
}

4. 延迟显示

4.1 基本延迟控制

kotlin
class MainActivity : AppCompatActivity() {
    
    override fun onCreate(savedInstanceState: Bundle?) {
        // 方式 1:使用 addCallback(推荐)
        addSplashScreen().setKeepOnScreenCondition {
            // 返回 true 保持显示,false 则消失
            !isAppReady()
        }
        
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_main)
    }
    
    private var isReady = false
    
    private fun isAppReady(): Boolean {
        return isReady
    }
    
    // 初始化完成后标记为就绪
    private fun initializeApp() {
        viewModelScope.launch {
            // 加载必要的数据
            loadUserConfig()
            loadInitialData()
            
            // 标记完成
            isReady = true
            
            // SplashScreen 会自动消失
        }
    }
}

4.2 使用 SetKeepOnScreenCondition

kotlin
class MainActivity : AppCompatActivity() {
    
    private val viewModel: MainViewModel by viewModels()
    
    override fun onCreate(savedInstanceState: Bundle?) {
        addSplashScreen().setKeepOnScreenCondition {
            // 基于 ViewModel 状态决定
            viewModel.appState.value == AppState.Loading
        }
        
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_main)
        
        // 观察状态变化
        lifecycleScope.launch {
            viewModel.appState.collect { state ->
                when (state) {
                    is AppState.Ready -> {
                        // 应用准备完成,SplashScreen 会消失
                    }
                    is AppState.Error -> {
                        // 处理错误
                    }
                }
            }
        }
    }
}

// ViewModel
class MainViewModel : ViewModel() {
    
    sealed class AppState {
        object Loading : AppState()
        data class Ready(val data: Data) : AppState()
        data class Error(val message: String) : AppState()
    }
    
    private val _appState = MutableStateFlow<AppState>(AppState.Loading)
    val appState: StateFlow<AppState> = _appState.asStateFlow()
    
    init {
        initialize()
    }
    
    private fun initialize() {
        viewModelScope.launch {
            try {
                val data = repository.loadInitialData()
                _appState.value = AppState.Ready(data)
            } catch (e: Exception) {
                _appState.value = AppState.Error(e.message ?: "Unknown error")
            }
        }
    }
}

4.3 最小显示时间

kotlin
class MainActivity : AppCompatActivity() {
    
    private var splashStartTime = 0L
    private val MIN_SPLASH_DURATION = 1500L // 至少显示 1.5 秒
    
    override fun onCreate(savedInstanceState: Bundle?) {
        splashStartTime = System.currentTimeMillis()
        
        addSplashScreen().setKeepOnScreenCondition {
            val elapsed = System.currentTimeMillis() - splashStartTime
            val isAppReady = isAppReady()
            
            // 确保至少显示 MIN_SPLASH_DURATION 毫秒
            !isAppReady || elapsed < MIN_SPLASH_DURATION
        }
        
        super.onCreate(savedInstanceState)
    }
    
    private fun isAppReady(): Boolean {
        // 检查应用是否准备就绪
        return true
    }
}

4.4 异步加载处理

kotlin
class MainActivity : AppCompatActivity() {
    
    private var isInitialized = false
    private val initJob = Job()
    private val initScope = CoroutineScope(Dispatchers.IO + initJob)
    
    override fun onCreate(savedInstanceState: Bundle?) {
        addSplashScreen().setKeepOnScreenCondition {
            !isInitialized
        }
        
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_main)
        
        // 启动初始化
        initScope.launch {
            performAsyncInitialization()
            isInitialized = true
        }
    }
    
    private suspend fun performAsyncInitialization() {
        withContext(Dispatchers.IO) {
            // 模拟耗时操作
            delay(2000)
            loadUserPreferences()
            checkAuthentication()
            loadRemoteConfig()
        }
    }
    
    override fun onDestroy() {
        initJob.cancel()
        super.onDestroy()
    }
}

5. 图标动画

5.1 静态图标

xml
<!-- res/values/themes.xml -->
<style name="Theme.App.Starting" parent="Theme.SplashScreen">
    <item name="windowSplashScreenBackground">@color/primary</item>
    <!-- 静态图标 -->
    <item name="windowSplashScreenAnimatedIcon">@drawable/logo_static</item>
    <item name="postSplashScreenTheme">@style/Theme.App</item>
</style>

5.2 矢量动画图标(Android 12+)

xml
<!-- res/drawable/logo_animation.xml -->
<objectAnimator xmlns:android="http://schemas.android.com/apk/res/android"
    android:duration="1500">
    
    <propertyValuesHolder
        android:propertyName="scaleX"
        android:valueType="floatType"
        android:valueFrom="0.0"
        android:valueTo="1.0" />
    
    <propertyValuesHolder
        android:propertyName="scaleY"
        android:valueType="floatType"
        android:valueFrom="0.0"
        android:valueTo="1.0" />
    
    <propertyValuesHolder
        android:propertyName="alpha"
        android:valueType="floatType"
        android:valueFrom="0.0"
        android:valueTo="1.0" />
    
</objectAnimator>

5.3 Lottie 动画

kotlin
// 1. 添加 Lottie 依赖
// implementation("com.airbnb.android:lottie:6.1.0")

// 2. 准备 Lottie 动画文件
// res/raw/logo_animation.json

// 3. 在主题中配置(需要使用自定义实现)
class MainActivity : AppCompatActivity() {
    
    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        
        // 对于复杂的动画,可能需要自定义 View
        // SplashScreen API 目前主要支持矢量动画
    }
}

5.4 创建动画图标

xml
<!-- res/drawable/splash_logo_animated.xml -->
<!-- 使用 animator 创建简单的缩放和淡入效果 -->
<animated-vector 
    xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:aapt="http://schemas.android.com/aapt"
    android:drawable="@drawable/splash_logo_base">
    
    <target android:name="logo_group">
        <aapt:attr name="android:animation">
            <set>
                <objectAnimator
                    android:propertyName="translateX"
                    android:duration="500"
                    android:valueFrom="-100"
                    android:valueTo="0"
                    android:valueType="floatType"
                    android:interpolator="@android:anim/decelerate_interpolator" />
                
                <objectAnimator
                    android:propertyName="scaleX"
                    android:duration="500"
                    android:valueFrom="0.5"
                    android:valueTo="1.0"
                    android:valueType="floatType"
                    android:interpolator="@android:anim/decelerate_interpolator" />
                
                <objectAnimator
                    android:propertyName="scaleY"
                    android:duration="500"
                    android:valueFrom="0.5"
                    android:valueTo="1.0"
                    android:valueType="floatType"
                    android:interpolator="@android:anim/decelerate_interpolator" />
            </set>
        </aapt:attr>
    </target>
    
</animated-vector>

6. 深色模式支持

6.1 自动深色模式适配

xml
<!-- res/values/themes.xml -->
<resources>
    <style name="Theme.App.Starting" parent="Theme.SplashScreen">
        <item name="windowSplashScreenBackground">@color/splash_bg_light</item>
        <item name="windowSplashScreenAnimatedIcon">@drawable/logo_for_light</item>
        <item name="windowSplashScreenIconBackgroundColor">?attr/colorPrimary</item>
        <item name="postSplashScreenTheme">@style/Theme.App</item>
    </style>
</resources>

<!-- res/values-night/themes.xml -->
<resources>
    <style name="Theme.App.Starting" parent="Theme.SplashScreen">
        <item name="windowSplashScreenBackground">@color/splash_bg_dark</item>
        <item name="windowSplashScreenAnimatedIcon">@drawable/logo_for_dark</item>
        <item name="windowSplashScreenIconBackgroundColor">?attr/colorPrimaryDark</item>
        <item name="postSplashScreenTheme">@style/Theme.App</item>
    </style>
</resources>

6.2 颜色资源定义

xml
<!-- res/values/colors.xml -->
<resources>
    <color name="splash_bg_light">#FFFFFF</color>
    <color name="splash_bg_dark">#121212</color>
    <color name="icon_background_light">#F5F5F5</color>
    <color name="icon_background_dark">#1E1E1E</color>
</resources>

6.3 动态深色模式检测

kotlin
class MainActivity : AppCompatActivity() {
    
    override fun onCreate(savedInstanceState: Bundle?) {
        // 检测系统深色模式设置
        val isDarkMode = resources.configuration.uiMode and 
            Configuration.UI_MODE_NIGHT_MASK == Configuration.UI_MODE_NIGHT_YES
        
        // 可以根据深色模式调整 SplashScreen 行为
        if (isDarkMode) {
            // 深色模式特定逻辑
        }
        
        super.onCreate(savedInstanceState)
    }
}

7. 性能优化

7.1 减少启动时间

kotlin
class MainActivity : AppCompatActivity() {
    
    override fun onCreate(savedInstanceState: Bundle?) {
        // 1. 延迟非关键初始化
        addSplashScreen().setKeepOnScreenCondition {
            !isCriticalInitComplete()
        }
        
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_main)
        
        // 2. 非关键操作延迟执行
        lifecycleScope.launch {
            delay(500) // 延迟执行
            performNonCriticalInit()
        }
    }
    
    private var criticalComplete = false
    
    private fun isCriticalInitComplete(): Boolean {
        return criticalComplete
    }
    
    // 只执行关键初始化
    private fun criticalInit() {
        // 必要的初始化
        criticalComplete = true
    }
    
    // 非关键操作
    private fun performNonCriticalInit() {
        // 广告 SDK 初始化
        // 分析数据上传
        // 预加载非关键资源
    }
}

7.2 预加载优化

kotlin
class MainActivity : AppCompatActivity() {
    
    override fun onCreate(savedInstanceState: Bundle?) {
        addSplashScreen().setKeepOnScreenCondition {
            !isPreloadComplete()
        }
        
        super.onCreate(savedInstanceState)
        
        // 预加载关键资源
        preloadCriticalResources()
    }
    
    private var preloadComplete = false
    
    private fun isPreloadComplete(): Boolean = preloadComplete
    
    private fun preloadCriticalResources() {
        viewModelScope.launch {
            withContext(Dispatchers.IO) {
                // 预加载图片
                imagePlaceholder = loadPlaceholder()
                
                // 预加载配置
                appConfig = loadConfig()
                
                // 预加载数据库
                database = initDatabase()
                
                preloadComplete = true
            }
        }
    }
}

7.3 启动时间监控

kotlin
class StartupMonitor {
    
    companion object {
        private var startupStartTime: Long = 0
        
        fun onStart() {
            startupStartTime = System.currentTimeMillis()
        }
        
        fun onComplete(tag: String) {
            val elapsed = System.currentTimeMillis() - startupStartTime
            Log.d("Startup", "$tag: ${elapsed}ms")
        }
    }
}

class MainActivity : AppCompatActivity() {
    
    override fun onCreate(savedInstanceState: Bundle?) {
        StartupMonitor.onStart()
        
        addSplashScreen().setKeepOnScreenCondition {
            !isAppReady()
        }
        
        super.onCreate(savedInstanceState)
        
        StartupMonitor.onComplete("SplashScreen")
        
        setContentView(R.layout.activity_main)
        
        StartupMonitor.onComplete("ContentReady")
    }
}

8. 最佳实践

8.1 推荐配置

xml
<!-- res/values/themes.xml -->
<resources>
    <!-- 启动主题最佳实践 -->
    <style name="Theme.App.Starting" parent="Theme.SplashScreen">
        <!-- 1. 使用品牌色作为背景 -->
        <item name="windowSplashScreenBackground">@color/brand_primary</item>
        
        <!-- 2. 使用优化过的矢量图标 -->
        <item name="windowSplashScreenAnimatedIcon">@drawable/brand_logo</item>
        
        <!-- 3. 设置图标背景(可选) -->
        <item name="windowSplashScreenIconBackgroundColor">@color/brand_accent</item>
        
        <!-- 4. 指定主主题 -->
        <item name="postSplashScreenTheme">@style/Theme.App</item>
    </style>
    
    <!-- 主主题 -->
    <style name="Theme.App" parent="Theme.MaterialComponents.DayNight.NoActionBar">
        <item name="colorPrimary">@color/brand_primary</item>
        <item name="colorPrimaryVariant">@color/brand_primary_dark</item>
        <item name="colorOnPrimary">@color/white</item>
    </style>
</resources>

8.2 图标设计建议

kotlin
/**
 * SplashScreen 图标设计最佳实践:
 * 
 * 1. 使用矢量图形(XML 或 Lottie)
 * 2. 保持图标简洁,易于识别
 * 3. 确保在圆形裁剪中良好显示
 * 4. 考虑深浅色模式的对比度
 * 5. 动画时长控制在 1-2 秒
 * 6. 文件大小尽量小
 */

8.3 测试要点

kotlin
/**
 * 测试清单:
 * 
 * ✅ 冷启动(应用完全关闭后启动)
 * ✅ 热启动(应用在前台)
 * ✅ 温启动(应用在后台)
 * ✅ 配置变化(屏幕旋转)
 * ✅ 深浅色模式切换
 * ✅ 不同 Android 版本
 * ✅ 不同屏幕尺寸
 * ✅ 快速返回(Back 后立即启动)
 */

9. 常见问题

9.1 闪屏问题

问题:SplashScreen 和应用主题之间有闪屏。

kotlin
// ❌ 错误:背景色不一致
<style name="Theme.App.Starting" parent="Theme.SplashScreen">
    <item name="windowSplashScreenBackground">@color/white</item>  <!-- 白色 -->
    <item name="postSplashScreenTheme">@style/Theme.App</item>
</style>

<style name="Theme.App" parent="Theme.MaterialComponents">
    <item name="colorPrimary">@color/blue</item>  <!-- 蓝色 -->
</style>

// ✅ 解决:确保颜色一致
<style name="Theme.App.Starting" parent="Theme.SplashScreen">
    <item name="windowSplashScreenBackground">@color/brand_primary</item>
    <item name="postSplashScreenTheme">@style/Theme.App</item>
</style>

9.2 图标不显示

问题:在旧设备上图标不显示。

kotlin
// 检查:
// 1. 是否添加了 core-splashscreen 依赖
// 2. 图标是否是正确的格式
// 3. 是否在主题中正确配置

10. 面试考点

10.1 基础考点

Q1: SplashScreen API 是什么?

参考答案

SplashScreen API 是 Android 12 引入的启动页 API,提供一致的品牌化启动体验,消除系统启动页和应用内容之间的闪屏。

Q2: 如何配置 SplashScreen?

参考答案

xml
<style name="Theme.App.Starting" parent="Theme.SplashScreen">
    <item name="windowSplashScreenBackground">@color/background</item>
    <item name="windowSplashScreenAnimatedIcon">@drawable/logo</item>
    <item name="postSplashScreenTheme">@style/Theme.App</item>
</style>

10.2 进阶考点

Q3: 如何控制 SplashScreen 的显示时间?

参考答案

kotlin
addSplashScreen().setKeepOnScreenCondition {
    !isAppReady()
}

10.3 高级考点

Q4: SplashScreen API 的兼容性如何保证?

参考答案

使用 androidx.core:core-splashscreen 库可以支持 Android 5.0+ 的设备。


总结

SplashScreen API 是现代 Android 应用的重要特性:

  1. 消除闪屏:系统启动页和应用启动页无缝衔接
  2. 品牌一致性:统一的品牌体验
  3. 易于实现:简单的主题配置
  4. 向后兼容:支持 Android 5.0+
  5. 性能优化:减少启动时间

📚 参考资料

最后更新:2024 年 字数统计:约 10000 字