如何加快Android應用啟動速度

NO IMAGE

     好的產品經理知道怎麼做減法,在重要的地方只放重要的東西,這樣出來的是簡潔的應用,比如微信。不好的產品經理只會想著在重要的地方展示儘可能多的東西,這樣出來的就是亂七八糟的首頁,例子嘛,呵呵

       但產品經理是頭,那程式狗就加吧。於是首頁上的東西越來越多。終於有一天,老闆吐槽了,xxx,你們的程式起來怎麼這麼慢啊,趕緊優化!

—————————-吐槽分割線—————————-

先說總結。其一,不管你是不是真變快了,至少讓使用者覺得你變快了。其二,能不做的事就不做,能後做的事不先做,絕不浪費。其三,流程合併,減少中間步驟。

      先說說之前程式啟動時的問題。使用者從Launcher點選我們的圖示,首先開啟的是一個splash activity,這個activity既作為一個logo展示等待頁面,又是一個動作分流地。在這裡根據是否有使用者,以及傳入的intent決定後面再打卡哪個activity。一般情況下,都是進入使用者看到的首頁。為了量化即將進行的優化,我用了一臺HTC one,並保持要載入的資料量基本不變。優化之前,從點開icon,到首頁資料載入完畢,總共大概是9秒。下面就一步一步開始優化。

首先,還是想著從黑科技上著手。不是啟動慢嗎,那我想辦法讓程式在點開我們的app之前,就讓程式先爬起來。我們不是神,沒法知道使用者什麼時候會點我,那怎麼辦呢?兩方面。一是讓我們的程式儘可能一直留在記憶體中,別被系統殺掉。根據android系統的規則,就是要提高我們程序的優先順序。程序優先順序可以通過cat /proc/pid/oom_adj檢視。當我們程序切到後臺後,以前就會變成一個後臺程序,進入快取的應用列表裡面,這裡隨時都可能會被殺掉,可以通過給程序新增一個service來將其變為一個服務程序,一下子,它就變成小強了。第二,我們還是可以稍微預測一下使用者行為的。至少,當使用者收到訊息後,他還是很可能會點開程式的。這時候,我們可以先把它給先爬起來。通過這一步,當使用者收到訊息後,再點開程式,啟動速度大概能減少1秒。

      其次,首頁上東西太多,初始化需要做的事情實在是太多了。我們得讓它少做一點事。我們首頁上是一個ViewPager,裡面有5幀內容,為了滑動流暢,5幀全部預載入進來了。之前太實誠了,全部載入進來幹嘛啊。這個地方方式就比較簡單了,按需載入即可。當然,為了,滑動不卡頓,每一幀還是先載入一個空殼和一個等待圖示,然後划過來的時候先在後臺載入資料,然後inflate view,掛到空殼下面。這麼做了之後,程式啟動時間縮短到了大約6點幾秒。不過,因為涉及到載入流程的改變,要注意資料改變時UI更新時是否存在,初始化各幀介面時是否有初始一些全域性資料等。

     再然後,因為每次啟動到首頁之前,都還要先經歷一個splash activity,如果能把這一步去掉,啟動速度必然又能大幅提升一把。去掉這個activity還是比較容易的。因為使用者已經安裝過我們的程式,launcher上的圖示對應的activity已經固定,所以我選擇保留原來的SplashActivity,抽取他的功能到另外一個輔助類,然後把原來的首頁調整為一個Fragment,動態新增到SplashActivity上。做到這裡,啟動時間刷刷的都蹭到了4秒左右。目的基本達到了,反正不比主要競品差了。

      在合併啟動頁的時候碰到了另外一個問題。之前首頁是從ActionBarActivity繼承,而且必須保留ActionBar的,而SplashActivity必須具有全屏屬性。想在Activity的OnCreate裡面hide actionbar,然後等載入完再顯示是行不通的,這時候開始的啟動畫面還是會帶有actionbar,然後等到快啟動完的時候才小時一下,然後在顯示出來。因為Android啟動程式是先從Zygote孵化出來,然後到Application的onCreate,然後到intent對應的元件。在Application建立之前,系統就會先解析啟動介面的theme,然後將這個介面的背景先顯示出來。如果要在一開始不顯示actionbar,只能在theme裡面就指定不要它。然後再在onCreate裡面通過requestFeature把他新增回去。V7包20.0版本之前的requestFeature實現是有問題的,android
4.2以上版本調了它之後還是不會有actionbar,需要通過反射將ActionBarActivityDelegate的mHasActionBar變數置為true才行。當然,你也可以選擇不要從ActionBarActivity繼承,而是直接從FragmentActivity繼承,然後自己實現ActionBar。或者升級一下V7包的版本,它後面又給修正了。。。

      再就是背景問題,一開始系統會先顯示theme裡指定的背景。所以,給theme選擇一個好的背景也是很重要的。優化之前,我們指定的是一個透明背景,這樣子用它做中繼Activity時使用者不會先看到一個多餘的背景。但有一個壞處是每次點app的icon時,都會顯得先卡頓了一下。啟動頁合併之後,再用它就沒必要了,因為我們的首頁是一直存在的。把背景直接改為logo頁,這時候再點選icon,卡頓就再也不存在了,直接如絲般順滑啊。

      最後再讚美一下Android L,啟動不用9秒,也不用4秒,甚至不用1秒,直接秒開啊!真的秒開。簡直要秒殺ios的節奏。 雖說有其他相容問題,但流暢性真的是槓槓的。