Android中App啓動優化

現在微信小程序火爆異常,各種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一般都會運行在新的進程,所以這個問題可能很多產品都有,值得關注。


發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章