Android性能優化之加快應用啟動速度 [復制鏈接]

2018-9-12 09:58
EmailLi 閱讀:663 評論:0 贊:1
Tag:  

應用的啟動

啟動方式

通常來說,在安卓中應用的啟動方式分為兩種:冷啟動和熱啟動。

1、冷啟動:當啟動應用時,后臺沒有該應用的進程,這時系統會重新創建一個新的進程分配給該應用,這個啟動方式就是冷啟動。

2、熱啟動:當啟動應用時,后臺已有該應用的進程(例:按back鍵、home鍵,應用雖然會退出,但是該應用的進程是依然會保留在后臺,可進入任務列表查看),所以在已有進程的情況下,這種啟動會從已有的進程中來啟動應用,這個方式叫熱啟動。

特點

1、冷啟動:冷啟動因為系統會重新創建一個新的進程分配給它,所以會先創建和初始化Application類,再創建和初始化MainActivity類(包括一系列的測量、布局、繪制),最后顯示在界面上。

2、熱啟動:熱啟動因為會從已有的進程中來啟動,所以熱啟動就不會走Application這步了,而是直接走MainActivity(包括一系列的測量、布局、繪制),所以熱啟動的過程只需要創建和初始化一個MainActivity就行了,而不必創建和初始化Application,因為一個應用從新進程的創建到進程的銷毀,Application只會初始化一次。

上面說的啟動是點擊app的啟動圖標來啟動的,而另外一種方式是進入最近使用的列表界面來啟動應用,這種不應該叫啟動,應該叫恢復。

應用啟動的流程

在安卓系統上,應用在沒有進程的情況下,應用的啟動都是這樣一個流程:當點擊app的啟動圖標時,安卓系統會從Zygote進程中fork創建出一個新的進程分配給該應用,之后會依次創建和初始化Application類、創建MainActivity類、加載主題樣式Theme中的windowBackground等屬性設置給MainActivity以及配置Activity層級上的一些屬性、再inflate布局、當onCreate/onStart/onResume方法都走完了后最后才進行contentView的measure/layout/draw顯示在界面上,所以直到這里,應用的第一次啟動才算完成,這時候我們看到的界面也就是所說的第一幀。

所以,總結一下,應用的啟動流程如下:

Application的構造器方法——>attachBaseContext()——>onCreate()——>Activity的構造方法——>onCreate()——>配置主題中背景等屬性——>onStart()——>onResume()——>測量布局繪制顯示在界面上。

測量應用啟動的時間

在上面這個啟動流程中,任何一個地方有耗時操作都會拖慢我們應用的啟動速度,而應用啟動時間是用毫秒度量的,對于毫秒級別的快慢度量我們還是需要去精確的測量到到底應用啟動花了多少時間,而根據這個時間來做衡量。

什么才是應用的啟動時間

從點擊應用的啟動圖標開始創建出一個新的進程直到我們看到了界面的第一幀,這段時間就是應用的啟動時間。

我們要測量的也就是這段時間,測量這段時間可以通過adb shell命令的方式進行測量,這種方法測量的最為精確,命令為:

adb shell am start -W [packageName]/[packageName.MainActivity]

執行成功后將返回三個測量到的時間:

1、ThisTime:一般和TotalTime時間一樣,除非在應用啟動時開了一個透明的Activity預先處理一些事再顯示出主Activity,這樣將比TotalTime小。

2、TotalTime:應用的啟動時間,包括創建進程+Application初始化+Activity初始化到界面顯示。

3、WaitTime:一般比TotalTime大點,包括系統影響的耗時。

下面是測量一個應用冷啟動和熱啟動的時間:

冷啟動:

熱啟動:

可以看到在進程已經存在的情況下,只需要重新初始化MainActivity,這樣的啟動比較快,不過大多數情況下應用的啟動都是冷啟動,因為用戶都會在任務列表中手動關閉遺留的應用進程。

減少應用啟動時的耗時

針對冷啟動時候的一些耗時,如上測得這個應用算是中型的app,在冷啟動的時候耗時已經快700ms了,如果項目再大點在Application中配置了更多的初始化操作,這樣將可能達到1s,這樣每次啟動都明顯感覺延遲,所以在進行應用初始化的時候采取以下策略:

1、在Application的構造器方法、attachBaseContext()、onCreate()方法中不要進行耗時操作的初始化,一些數據預取放在異步線程中,可以采取Callable實現。

2、對于sp的初始化,因為sp的特性在初始化時候會對數據全部讀出來存在內存中,所以這個初始化放在主線程中不合適,反而會延遲應用的啟動速度,對于這個還是需要放在異步線程中處理。

3、對于MainActivity,由于在獲取到第一幀前,需要對contentView進行測量布局繪制操作,盡量減少布局的層次,考慮StubView的延遲加載策略,當然在onCreate、onStart、onResume方法中避免做耗時操作。

遵循上面三種策略可明顯提高app啟動速度。

優化應用啟動時的體驗

對于應用的啟動時間,只能是盡量的避免一些耗時的、非必要的操作在主線程中,這樣相對可以縮減一部分啟動的耗時,另外一方面在等待第一幀顯示的時間里,可以加入一些配置以增加體驗,比如加入Activity的background,這個背景會在顯示第一幀前提前顯示在界面上。1、先為主界面單獨寫一個主題style,設置一張待顯示的圖片,這里我設置了一個顏色,然后在manifest中設置給MainActivity:

<style name="AppTheme.Launcher"> <item name="android:windowBackground">@drawable/bule</item> </style>
//...
        <activity  android:name=".MainActivity" android:label="@string/app_name" android:theme="@style/AppTheme.Launcher">
            <intent-filter>
                <action android:name="android.intent.action.MAIN" />
                <category android:name="android.intent.category.LAUNCHER" />
            </intent-filter>
        </activity>

2、然后在MainActivity中加載布局前把AppTheme重新設置給MainActivity:

@Override
    protected void onCreate(Bundle savedInstanceState) {

        setTheme(R.style.AppTheme);
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
}        

這樣在啟動時會先顯示background,然后待界面繪制完成再顯示主界面


我來說兩句
您需要登錄后才可以評論 登錄 | 立即注冊
facelist
所有評論(0)
領先的中文移動開發者社區
18620764416
7*24全天服務
意見反饋:[email protected]

掃一掃關注我們

Powered by Discuz! X3.2© 2001-2019 Comsenz Inc.( 粵ICP備15117877號 )

两码中特期期