1. 程式人生 > >Android 解決APP啟動時出現白屏問題

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類,然後把它啟動起來。