App啟動優化

weixin_34138377發表於2016-09-30

現在微信小程式火爆異常,各種demo層出不窮,筆者也不免俗,一直有關注,雖然不是微信的死忠,但是不得不佩服微信的野心。開發難度不高再加上微信生態,感覺這個東西正式進入市場後必定對原生開發造成一定的影響,特別是一些創業公司因為考慮到原生開發的高成本,微信小程式不失為一種高效的途徑。建議大家也保持關注,並進行一些基礎的嘗試。

好了,言歸正傳。最近公司的一款產品應為啟動時間過長,所以做了一定的優化,而筆者有幸參與,現在主要記錄一下實踐過程。

通常來說,啟動方式分為兩種:冷啟動和熱啟動。

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

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

本文所指的優化針對冷啟動。簡單解釋一下App的啟動過程:

1.點選Launcher,啟動程式,通知ActivityManagerService

2.ActivityManagerService通知zygote程式孵化出應用程式,分配記憶體空間等

3.執行該應用ActivityThread的main()方法

4.應用程式通知ActivityManagerService它已經啟動,ActivityManagerService儲存一個該應用的代理物件,ActivityManagerService通過它可以控制應用程式

5.ActivityManagerService通知應用程式建立入口的Activity例項,執行它的生命週期

啟動過程中Application和入口Activity的生命週期方法按如下順序呼叫:

1.Application 構造方法

2.attachBaseContext()

3.onCreate()

4.入口Activity的物件構造

5.setTheme() 設定主題等資訊

6.入口Activity的onCreate()

7.入口Activity的onStart()

8.入口Activity的onResume()

9.入口Activity的onAttachToWindow()

10.入口Activity的onWindowFocusChanged()

理論上來說當回撥到入口Activity的onResume()方法時,App就算正式啟動了,但是從這種意義上其實是不嚴謹的,因為在這個時間點

實際只完成了主題資訊以及view樹建立等。而view繪製的真正過程measure layout draw過程並沒有,所以不是真正意義上的“可見”。  在onWindowFocusChanged()回撥處更接近事實。所以我們確認啟動時間可以從Application的構造方法記錄開始時間,然後到入口Activity的onWindowFocusChanged()再記錄一個時間,兩者之差就是App的啟動時間。當然這是比較笨的方法,adb命令裡有相應的記錄命令 :adb shell am start -W 包名/入口類全路徑名 ,打出來的時間會有三個,分別是ThisTime,TotalTime,WaitTime,我們要取TotalTime作為標準。

有了這些準備知識,我們就要了解App啟動為什麼會緩慢。就筆者公司產品來說通過多次打點記錄時間差,發現了主要的原因是在application和activity的啟動生命週期中過多耗時的操作,重災區是Application的attachBaseContext()和

onCreate()方法,因為業務的需要整合了大量第三方sdk以及本公司封裝的一些sdk,比較耗時的有okhttp模組初始化(應業務需要改裝過),公司封裝的一天混合開發框架(其中會解析本地的一份很長的配置檔案,解壓本地的H5頁面資源包,初識化定位資訊),還有很多其他的操作。重新審視程式碼發現有些操作不必再這兩個方法做,完全可以等到頁面出來後再在後臺去做,即可以放到入口Activity的onWindowFocusChanged()方法中做。優化前後在魅族MX4上對比,優化前平均值大概是5.6s,優化後平均值大概是1.9s。

其實App啟動緩慢的原因肯能多種多樣,但是思路都是一樣的,最主要的是掌握App啟動的過程,然後再針對自己的產品分析,哪些初始化步驟可以在頁面出來後再去做。

另外在優化過程中發現了application oncreate()方法多次執行,導致多次不必要的初始化,耗電耗記憶體耗速度。原因是應用程式中除了主程式還有兩個子程式分別是push子程式(第三方push sdk的程式空間),remote子程式(百度定位sdk的程式空間)主程式啟動後,會再啟動這兩個子程式, 重新執行了onCreate()方法。實際這裡面的初始化程式碼跟它們都無關。百度sdk的initialize過程,在我們主程式中呼叫的)。解決辦法就是在onCreate()時通過判斷當前程式名,如果不是主程式則不走後續的邏輯。相信很多產品可能都整合推送sdk以及地圖定位的sdk,這些sdk一般都會執行在新的程式,所以這個問題可能很多產品都有,值得關注。


1465955-a8dacc83ee43f5b1.jpeg

                                                             掃碼可關注本公眾號

相關文章