1. 程式人生 > >Android應用冷啟動解析和優化方案

Android應用冷啟動解析和優化方案

前言

在我們點選Android手機桌面APP圖示時,有時候我麼會發現,應用並不是直接進入閃屏頁或者應用主頁面,而是會有一個短暫時間的白屏才能進去。但如果我們點選Back鍵退出應用,在點選返回的時候卻沒有白屏或者白屏時間幾乎不可見。為什麼會出現這種情況呢?這就涉及到Android應用冷熱啟動的問題。

啟動方式

Android應用的啟動方式可以分為三種:冷啟動,暖啟動,熱啟動;不同的啟動方式表示著應用載入的方式不同,相對應的就產生了應用UI呈現給使用者所需要花費的時間不同。

啟動時間

Android 4.4(API 19)開始,Logcat可以自動打印出應用的啟動時間,這個時間值從應用啟動(建立程序)開始計算,到完成是檢視的而第一次繪製(第一個Activity的介面第一次對使用者可見)為止。


Cold Start (冷啟動)

什麼是冷啟動? 比如裝置開機後應用第一次啟動,系統殺死應用程序(包括:使用者主動殺死程序和系統記憶體吃緊引發的Kill)再次啟動等。

在Android系統中,APP啟動時,系統為每個執行的應用至少分配一個程序(多執行緒應用申請多個程序)。從程序角度講,應該冷啟動的時候,是沒有該應用的程序配置資訊的(包括 Application ,四大元件等),這樣冷啟動是所做的工作就會比其他兩種啟動方式多。

冷啟動時,系統主要任務有兩件:

1,開始載入並啟動APP;

2,建立應用程序資訊,進入並顯示第一個Activity UI。

而我們我看到的白屏就是在第二步,配置程序資訊和第一個Activity UI渲染到頁面之前所花費的時間。那麼我們來分析一下系統建立應用程序後,所要處理的事情;

1,初始化應用中的物件(比如Application的建立及其onCreate中的工作)

2,啟動主執行緒;

3,建立第一個Activity;

4,載入佈局檢視(Inflating);

5,初始化控制元件在螢幕上的位置(Laying out)

6,繪製檢視(draw)

只有當應用完成第一次繪製,系統當前展現的空白背景才會被Activity的佈局檢視替換掉。這是使用者才能應用進行互動。在這個流程中主要涉及到Application 的onCreate和第一個Activity的onCreate方法,它們均在View繪製展示之前進行處理。所以在應用自定義的Application類中和第一個Activity類中的onCreate方法處理的邏輯越多,冷啟動花費的時間就越長。

Warm Start (暖啟動)

當APP中的Activities被銷燬,但在記憶體中常駐時,應用的啟動方式就會變為暖啟動。相比於冷啟動,暖啟動過程減少了物件的初始化,佈局載入等工作,啟動時間會縮短。但啟動時,系統忍讓會展現一個空白背景,直到第一個Activity的內容替換。

Lukewarm Start (熱啟動)

熱啟動產生的場景有很多,比如:使用者點選Back鍵退出應用,然後馬上就重新啟動。這是佈局依舊是之前繪製好的,所以花費的時間更少。

優化方案

應用的冷啟動是無法避免的,也就是說冷啟動時使用者總需要經歷一個等待啟動時間。開發人員唯一能做的就是在 Application 和 第一個 Activity 中,減少 onCreate() 方法的工作量,從而縮短冷啟動的時間。像應用中嵌入的一些第三方 SDK,都建議在 Application 中做一些初始化工作,開發人員不妨採取懶載入的形式移除這部分程式碼,而在真正需要用到第三方 SDK 時再進行初始化。

除此之外,還有一種方式就是通過設定應用主題背景的方法,把應用預設展現的白色背景替換被透明背景。我們新建一個主題樣式:

   <style name="LaunchStyle" parent="AppTheme">
        <!--設定透明背景-->
        <!--<item name="android:windowIsTranslucent">true</item>-->
        <!--設定無標題-->
        <!--<item name="android:windowNoTitle">true</item>-->
    </style>
然後在AndroidManifast.xml檔案中將主題設定給第一個啟動的Activity
<application
    android:name=".MyApplication"
    android:allowBackup="true"
    android:icon="@mipmap/ic_launcher"
    android:label="@string/app_name"
    android:supportsRtl="true">
    <activity
        android:name=".MainActivity"
        android:theme="@style/MyStyle">
        <intent-filter>
            <action android:name="android.intent.action.MAIN" />
            <category android:name="android.intent.category.LAUNCHER" />
        </intent-filter>
    </activity>
</application>
然後在修改MainActivity的onCreate中,在setContentView(R.layout.avtivity_main)載入佈局之前把主題修改回來
@Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setTheme(R.style.AppTheme);
        setContentView(R.layout.activity_main);
    }

我們可以看到現在白屏是沒有了,這是應為我們將應用主題背景設定為透明,在我們點選應用圖示之後,其實就已經打開了應用,不過此時應用背景為透明,我們讓看到的是桌面。雖然這樣做白屏是沒有了,但是我們可以明顯看到應用開啟呈現一種卡頓延遲的現象。這種效果相比於白屏更不可取(這是因為我在Aplication的onCreate方法中休眠了三秒)

public class MyApplication extends Application {
    @Override
    public void onCreate() {
        super.onCreate();
        try {
            Thread.sleep(3000);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }
}

除了上邊這種方法,還有一種更好的解決思路。就是通過android:windowBackground" 設定自定義主題背景,這樣就給到使用者一種很好的視覺過渡效果。可以參考優酷APP效果,直接將原本展示白屏的頁替換成應用的閃屏頁。

<style name="LaunchStyle" parent="AppTheme">
        <!--設定Appliction背景-->
        <item name="android:windowBackground">@drawable/layout_launch</item>
</style>
<?xml version="1.0" encoding="utf-8"?>
<layer-list xmlns:android="http://schemas.android.com/apk/res/android"
    android:opacity="opaque">

    <item android:drawable="@color/color_white" />
    <item>
        <bitmap
            android:gravity="center"
            android:src="@mipmap/baidu" />
    </item>

</layer-list>

這是最終的效果,當然如果新增些動畫效果會更好。