各位戰士,歡迎來到第十三天的戰場。至今,我們所有的努力都集中在「縮短」冷啟動的時間上。但無論我們優化得多好,從使用者點擊圖示到 App 完全可互動,總會有一個短暫的等待期。
這段時間,使用者看到的是什麼?是短暫的白畫面?還是設計粗糙的啟動圖?這第一印象至關重要。一個糟糕的閃屏頁不僅會讓前面的速度優化成果大打折扣,甚至可能給使用者帶來「這個 App 很慢」的錯覺。
今天,我們的任務就是將這段等待時間,從一段惱人的延遲,轉變為一次優雅、無縫的品牌展示。
postDelayed
的延遲閃屏在古老的戰場上,許多開發者會用一種錯誤的方式來實作閃屏頁:
SplashActivity
,其佈局只有一個 Logo。onCreate
中使用 Handler.postDelayed()
或類似的計時器。MainActivity
並關閉自己。這是一個災難性的戰術!
它不僅沒有解決冷啟動時的白畫面問題,反而人為地增加了不必要的等待時間。使用者被迫看完一個固定的動畫,即便 App 本身已經準備好了。這種做法違背了我們性能優化的初衷。在我們的戰爭中,這是必須被拋棄的戰術。
windowBackground
在 Android 12 出現之前,業界的最佳實踐是利用 windowBackground
屬性來消除冷啟動的白畫面。原理是:在系統為 App 建立主視窗時,立刻為這個視窗設定一個帶有 Logo 的背景,而不是等 Activity
的 setContentView()
執行完畢才顯示內容。
雖然這個方法依然有效,但現在我們有了更現代化、功能更強大的官方武器。
SplashScreen
APIGoogle 在 Android 12 中推出了一套全新的 SplashScreen
API,並透過 androidx.core:core-splashscreen
函式庫將其向後相容至所有 API Level。這是當前實作閃屏頁的唯一推薦方式。
它的優勢:
windowBackground
的靜態閃屏頁體驗。第一步:加入依賴
在你的 :app
模組的 build.gradle.kts
中,加入 SplashScreen
函式庫:
// In app/build.gradle.kts
dependencies {
// ... other dependencies
implementation("androidx.core:core-splashscreen:1.0.1") // 建議使用最新版本
}
在 res/values/themes.xml
中,建立一個專門用於閃屏頁的主題。它的 parent
必須是 Theme.SplashScreen
或其子類。
<style name="Theme.App.Starting" parent="Theme.SplashScreen">
<item name="windowSplashScreenBackground">@color/white</item>
<item name="windowSplashScreenAnimatedIcon">@drawable/ic_splash_logo</item>
<item name="postSplashScreenTheme">@style/Theme.MyApp</item>
</style>
打開 AndroidManifest.xml
,將你的啟動 Activity
(通常是 MainActivity
) 的 android:theme
屬性指向我們剛剛建立的 Theme.App.Starting
。
<activity
android:name=".MainActivity"
android:exported="true"
android:theme="@style/Theme.App.Starting"> <intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
最後,在你的啟動 Activity
的 onCreate
方法中,呼叫 installSplashScreen()
。
⚠️ 重要: 這個呼叫必須在 super.onCreate()
和 setContentView()
之前。
// In MainActivity.kt
import android.os.Bundle
import androidx.activity.ComponentActivity // or androidx.appcompat.app.AppCompatActivity
import androidx.activity.viewModels
import androidx.core.splashscreen.SplashScreen.Companion.installSplashScreen
class MainActivity : ComponentActivity() {
private val viewModel: MainViewModel by viewModels()
override fun onCreate(savedInstanceState: Bundle?) {
// Handle the splash screen transition.
val splashScreen = installSplashScreen() // ‼️ 必須在 super.onCreate() 之前
super.onCreate(savedInstanceState)
// [進階用法] 讓閃屏頁持續顯示,直到初始數據載入完畢
// 我們告訴閃屏頁:請保持顯示,直到 viewModel.isReady 的狀態變為 true
splashScreen.setKeepOnScreenCondition { !viewModel.isReady.value }
setContentView(R.layout.activity_main)
}
}
在上面的進階用法中,我們使用了 setKeepOnScreenCondition
。這是一個極其強大的功能,它允許 App 在 ViewModel
或其他地方非同步載入數據(例如從網路或資料庫讀取初始設定),同時保持閃屏頁的顯示。一旦數據準備就緒 (viewModel.isReady.value
變為 true
),條件不再滿足,閃屏頁就會播放退出動畫並自動消失。
今天,我們為啟動戰役畫上了完美的句點。我們學會了:
拋棄了 postDelayed
這種過時且有害的閃屏頁實作方式。
掌握了 SplashScreen
這個現代化、官方推薦的終極武器。
學會了 如何設定閃屏頁的主題,並在 Activity
中安裝它。
了解了 如何使用 setKeepOnScreenCondition
來優雅地處理數據預載,實現真正的無縫體驗。
速度與體驗,兩者兼得。至此,我們應用程式的「門面」已經煥然一新。使用者將在一次極速且流暢的啟動中,開啟我們的應用。
第一場大型戰役——應用啟動速度優化戰役——至此大獲全勝。明天,我們將對過去一週的戰果進行全面的數據檢視與總結,為下一場戰爭做好準備!
我們明天見!