相信大家都會有這樣的經歷,就是新創建的項目運行app後,發現會出現短時間的白屏或黑屏,然後才進入主界面。爲什麼會出現這樣的現象呢?谷歌工程師出於怎樣的考慮呢?我們該如何解決呢?基於這樣幾個問題,開始分析。
一、手機啓動流程
當我們點擊開機的時候,首先會通過引導芯片啓動Linux內核,通過它會創建init進程,然後孵化出Zygote進程。然後Zygote進程孵化出SystemServer進程,初始化JVM虛擬機。然後初始化AMS\PMS等系統服務,最後纔看到桌面的Launcher界面。具體得內部實現原理這裏不做分析,大家只需要大致瞭解流程即可。
二、app啓動方式
1、冷啓動
程序重新開始,系統沒有爲該app創建進程。一般是在app第一次啓動或者應用程序被系統完全清理。
1、熱啓動
程序依然存在內存中,只是從前臺到後臺。使用熱啓動不會走onCreate()方法,所以能夠避免重複的佈局的加載和渲染。需要注意的是如果程序被系統清理了,使用暖啓動需要重新初始化一些對象,防止空指針的出現。
1、暖啓動
它包含冷啓動和熱啓動一些列的操作子集,比熱啓動消耗稍微多一點,它與熱啓動最大的區別是它必須調用onCreate()方法重新初始化操作,也可以從onCreate()方法保存的實例來獲取某些對象的恢復。比如onCreate()方法參數中的Bundle對象,就可以存儲一些對象。
三、冷啓動流程
- 加載並啓動app
- 爲app創建一個空白的窗口
- 創建app進程
- 創建主activity
- 加載佈局、繪製
由於在啓動的過程中需要一系列的耗時操作,所以在冷啓動的過程中會爲app添加一個空白的窗口,防止用戶感覺到明顯的卡頓。這也是出現黑白屏的原因,黑白屏的顏色是根據Theme的顏色來定的。
四、黑白屏解決方案
1、方案1
<style name="AppTheme" parent="Theme.AppCompat.Light.DarkActionBar">
<!-- Customize your theme here. -->
<item name="colorPrimary">@color/colorPrimary</item>
<item name="colorPrimaryDark">@color/colorPrimaryDark</item>
<item name="colorAccent">@color/colorAccent</item>
<!--取消預覽-->
<item name="android:windowDisablePreview">true</item>
<!--背景設置爲透明-->
<item name="android:windowIsTranslucent">true</item>
</style>
可以取消預覽也可以設置窗體爲透明。這兩種方式都是一樣的效果。但是有一個缺點,就是當用戶點擊app圖標的時候需要等待一會,才能進入主界面,體驗不好,不推薦這種做法。
2、方案2
(1)在drawable下創建一個layer-list,代碼如下:
<layer-list xmlns:android="http://schemas.android.com/apk/res/android">
<!-- The background color, preferably the same as your normal theme -->
<item android:drawable="@android:color/holo_green_light"/>
<item android:top="150dp">
<bitmap android:gravity="top"
android:src="@mipmap/pay_cloud" />
</item>
</layer-list>
第一個item設置純色背景,第二個item設置一個圖標,距離頂部150dp。
(2)在styles.xml下創建一個Theme,代碼如下:
<style name="AppTheme.LaunchTheme">
<item name="android:windowBackground">@drawable/launch_layout</item>
<item name="android:windowFullscreen">true</item>
<item name="windowNoTitle">true</item>
</style>
windowBackground設置爲我們自己的layer-list。並且設置爲全屏顯示。
(3)在AndroidMainifet.xml爲我們的啓動頁設置Theme
<activity android:name=".SplashActivity" android:theme="@style/AppTheme.LaunchTheme">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
爲什麼對activity設置該theme,爲了不影響其他的activity,可擴展性好。
(4)啓動頁面佈局
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context=".SplashActivity">
<ImageView
android:id="@+id/go"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:src="@mipmap/pay_alipay"
android:layout_alignParentBottom="true"
android:layout_centerHorizontal="true"
android:layout_marginBottom="50dp"/>
</RelativeLayout>
只在底部添加了一張圖片。
五、運行效果
優化前:
優化後:
注意:一般閃屏頁需要設計成純色背景。如果使用一張圖片,就會增大內存佔用。所以說,最好的設計就是跟着系統走。