Android 解決APP啟動時出現白屏問題
1、問題描述
當我們首次啟動APP時,再到APP的第一個頁面展示出來之前,這段時間會有幾秒的白屏或者是黑屏出現。這樣給使用者的體驗是十分不好的。
2、問題出現的原因:
當我們在啟動一個應用時,系統會檢查是否已經存在這樣一個程序,如果沒有,Android系統會創建出一個新的程序分配給該應用,之後會依次建立和初始化Application類、然後啟動SplashActivity類的。而顯示白黑屏的問題就是在這段時間內產生的。
系統會在繪製頁面載入佈局之前 ,首先會初始化視窗(Window),而在進行這步操作時,系統會根據我們設定的Theme來指定它的Theme主題顏色。Window佈局的頂層是DecorView,StartingWindow顯示一個空的DecorView,進而我們在Style中的設定就決定了顯示的是白屏還是黑屏。
3、解決方法
就是在應用要啟動的第一個頁面中設定一個單獨的Theme主題
<application
android:name=".MyApplication"
android:allowBackup="true"
android:icon="@mipmap/ic_launcher"
android:label="@string/app_name"
android:roundIcon="@mipmap/ic_launcher_round"
android:supportsRtl="true"
android:theme="@style/AppTheme">
<activity
android:name=".ui.splash.SplashActivity"
android:theme="@style/SplashTheme"
android:configChanges="orientation|keyboardHidden|screenSize"
android:launchMode="singleTask"
android:screenOrientation ="landscape"
android:windowSoftInputMode="stateHidden|adjustPan">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
<!-- LAUNCHER -->
<category android:name="android.intent.category.HOME" />
<category android:name="android.intent.category.DEFAULT" />
</intent-filter>
</activity>
</application>
style主題
<!-- Application Theme-->
<style name="AppTheme" parent="Theme.AppCompat.DayNight.NoActionBar">
<!-- Customize your theme here. -->
<item name="colorPrimary">@color/colorPrimary</item>
<item name="colorPrimaryDark">@color/colorPrimaryDark</item>
<item name="colorAccent">@color/colorAccent</item>
</style>
<!--SplashActivity Theme-->
<style name="SplashTheme" parent="AppTheme">
<item name="android:windowIsTranslucent">true</item> <!-- 透明背景 -->
<item name="android:windowNoTitle">true</item>
<item name="android:windowContentOverlay">@null</item>
<item name="android:windowBackground">@drawable/bg</item>
<item name="android:windowFullscreen">true</item>
</style>
注意這裡的主題樣式,是針對所有的Activity繼承自AppCompatActivity設定的。否則會報錯不匹配。
4、拓展
(1)Activity和AppCompatActivity
繼承自Activity的不帶標題欄,繼承自AppCompatActivity的會帶標題欄
Android Support Library(安卓相容包)是為了構件一個可以跑在不同版本Android平臺的軟體。
重構AppCompat在新的AppCompat中,加入主題色,Toolbar等功能。在新版本中推薦使用AppCompatActivity代替ActionBarActivity。
(2)App的冷啟動與熱啟動
1、冷啟動:當啟動應用時,後臺沒有該應用的程序,這時系統會重新建立一個新的程序分配給該應用,這個啟動方式就是冷啟動。
2、熱啟動:當啟動應用時,後臺已有該應用的程序(例:按back鍵、home鍵,應用雖然會退出,但是該應用的程序是依然會保留在後臺,可進入任務列表檢視),所以在已有程序的情況下,這種啟動會從已有的程序中來啟動應用,這個方式叫熱啟動。
特點
1、冷啟動:冷啟動因為系統會重新建立一個新的程序分配給它,所以會先建立和初始化Application類,再建立和初始化MainActivity類(包括一系列的測量、佈局、繪製),最後顯示在介面上。
2、熱啟動:熱啟動因為會從已有的程序中來啟動,所以熱啟動就不會走Application這步了,而是直接走MainActivity(包括一系列的測量、佈局、繪製),所以熱啟動的過程只需要建立和初始化一個MainActivity就行了,而不必建立和初始化Application,因為一個應用從新程序的建立到程序的銷燬,Application只會初始化一次。
(3)App啟動的過程
1、點選桌面圖示,Launcher會啟動程式預設的Acticity,之後再按照程式的邏輯啟動各種Activity
2、啟動Activity都需要藉助應用程式框架層的ActivityManagerService服務程序(Service也是由ActivityManagerService程序來啟動的);在Android應用程式框架層中,ActivityManagerService是一個非常重要的介面,
它不但負責啟動Activity和Service,還負責管理Activity和Service。
①. 無論是通過Launcher來啟動Activity,還是通過Activity內部呼叫startActivity介面來啟動新的Activity,都通過Binder程序間通訊進入到ActivityManagerService程序中,並且呼叫ActivityManagerService.startActivity介面;
②. ActivityManagerService呼叫ActivityStack.startActivityMayWait來做準備要啟動的Activity的相關資訊;
③. ActivityStack通知ApplicationThread要進行Activity啟動排程了,這裡的ApplicationThread代表的是呼叫ActivityManagerService.startActivity介面的程序,對於通過點選應用程式圖示的情景來說,這個程序就是Launcher了,
而對於通過在Activity內部呼叫startActivity的情景來說,這個程序就是這個Activity所在的程序了;
④. ApplicationThread不執行真正的啟動操作,它通過呼叫ActivityManagerService.activityPaused介面進入到ActivityManagerService程序中,看看是否需要建立新的程序來啟動Activity;
⑤. 對於通過點選應用程式圖示來啟動Activity的情景來說,ActivityManagerService在這一步中,會呼叫startProcessLocked來建立一個新的程序,而對於通過在Activity內部呼叫startActivity來啟動新的Activity來說,這一步是不需要執行的,
因為新的Activity就在原來的Activity所在的程序中進行啟動;
⑥. ActivityManagerServic呼叫ApplicationThread.scheduleLaunchActivity介面,通知相應的程序執行啟動Activity的操作;
⑦. ApplicationThread把這個啟動Activity的操作轉發給ActivityThread,ActivityThread通過ClassLoader匯入相應的Activity類,然後把它啟動起來。