2016-07-18 09:53html
前言html5
最近部門內拋出了一個問題,應用啓動很慢、卡圖標?主要表如今中低端機型中。究其這個問題,因爲對性能優化比較感興趣,借了個低端機和一箇中端機來一看究竟,對同一應用分別測了下它在中低端機的啓動時間,下面爲啓動耗時狀況:瀏覽器
啓動了三次,基本都在4s左右。性能優化
緣由jsp
究其緣由,主要因素是任務在界面繪製前過於集中化。性能
應用啓動過程從用戶點擊launcher圖標到看到第一幀這個過程當中,主要會通過如下這些過程:優化
main()->Application:attachBaseContext()->onCreate()->Activity:onCreate()->onStart()->onPostCreate()->onResume()->onPostResume()spa
而通常咱們的初始化任務主要都會集中化在Application:onCreate()方法中,這就使得初始化任務在第一幀繪製以前得完成,這就形成了卡圖標、應用啓動慢。那麼把任務打散呢?分散在LaunchActivity中去分段初始化?仍是不行的,由於界面開始繪製是在onResume()方法開始後纔開始繪製,因此,得從Activity的建立過程找辦法。orm
main->Activity建立的這個過程會通過一系列framework層的操做,這些操做都是系統自動執行的,不易進行優化,不過能夠在Activity建立這個過程先後來找一些蛛絲馬跡,由於Activity的建立都會展轉到ActivityThread:performLaunchActivity()這個方法中,在這個方法中能夠知道這麼幾件事:htm
一、先經過Instrumentation:newActivity()來建立一個Activity實例
二、再判斷Application實例是否已建立,已建立則直接返回,不然調用
Instrumentation:newApplication()來建立Application實例,在這個過程當中會依次執行attachBaseContext()和onCreate()方法
三、以後Activity:attach()方法會建立一個PhoneWindow對象,它就是界面,它有一個DecorView,調用setContentView()時會給配置DecorView,其中就會設置一個背景:
咱們的View也是add進DecorView中顯示,它做爲RootView確定是最早顯示,因此能夠給它設置個默認背景
四、最後依次調用Activity的onCreate、onStart等方法
措施
一、任務分級
二、任務並行
三、界面預顯示
對於任務集中初始化化、耗時初始化緣由致使應用在中低端機啓動過慢,而Activity界面繪製的時機致使簡單的將任務分給Activity初始化也不起做用,咱們必須找一個切入點
界面的建立和界面的繪製,這兩個過程第一個是Application的attachBaseConte和onCreate這兩個方法影響的,第二個則是Application建立一直到界面繪製
因此,能夠對任務進行分級的臨界點能夠這樣分:
一、CoreSDK——Application的建立
二、HighPrioritySDK——Activity的建立
三、LowPrioritySDK——Activity界面完成繪製
四、AsyncSDK——Activity的建立
如圖:
對任務這樣分級後,測了一下,應用的啓動即便在低端機上,也能秒開:
分級帶來的問題
正常啓動過程那確定是沒問題的,不過有這麼幾種場景:
一、App切回後臺,內存不足致使Application被回收,從最近任務列表中恢復界面時Application需從新建立
二、應用沒掛起時,Push推送需從Notification跳入應用內某界面
三、應用沒掛起時,瀏覽器外鏈需跳入應用內某界面
這些Case可能致使的問題是被跳入的界面使用到了未初始化的SDK,可能致使Crash或者數據異常,因此目標頁面啓動前必須確保SDK已經初始化,這個過程的緣由是沒有喚起啓動頁來初始化SDK,能夠經過hook newActivity解決。