【騰訊Bugly乾貨分享】Android性能優化典範——第6季

本文來自於騰訊bugly開發者社區,非經做者贊成,請勿轉載,原文地址:http://dev.qq.com/topic/580d91208d80e49771f0a07chtml

導語

這裏是Android性能優化典範第6季的課程學習筆記,從被@知會到有連載更新,這篇學習筆記就一直被惦記着,如今學習記錄分享一下,請多多指教包涵!此次一共才6個小段落,涉及的內容主要有:程序啓動時間性能優化的三個方面:優化activity的建立過程,優化application對象的啓動過程,正確使用啓動顯屏達到優化程序啓動性能的目的。另外還介紹了減小安裝包大小的checklist以及如何使用VectorDrawable來減小安裝包的大小。android

1. App Launch time 101

提升程序的啓動速度意義重大,很顯然,啓動時間越短,用戶才越有耐心等待打開這個APP進行使用,反之啓動時間越長,用戶則越有可能來不及等到APP打開就已經切換到其餘APP了。程序啓動過程當中的那些複雜錯誤的操做極可能致使嚴重的性能問題。Android系統會根據用戶的操做行爲調整程序的顯示策略,用來提升程序的顯示性能。例如,一旦用戶點擊桌面圖標,Android系統會當即顯示一個啓動窗口,這個窗口會一直保持顯示直到畫面中的元素成功加載並繪製完第一幀。這種行爲常見於程序的冷啓動,或者程序的熱啓動場景(程序從後臺被喚起或者從其餘APP界面切換回來)。那麼關鍵的問題是,用戶極可能會由於從啓動窗口到顯示畫面的過程耗時過長而感到厭煩,從而致使用戶沒有來得及等程序啓動完畢就切換到其餘APP了。更嚴重的是,若是啓動時間過長,可能致使程序出現ANR。咱們應該避免出現這兩種糟糕的狀況。git

從技術角度來講,當用戶點擊桌面圖標開始,系統會當即爲這個APP建立獨立的專屬進程,而後顯示啓動窗口,直到APP在本身的進程裏面完成了程序的建立以及主線程完成了Activity的初始化顯示操做,再而後系統進程就會把啓動窗口替換成APP的顯示窗口。github

上述流程裏面的絕大多數步驟都是由系統控制的,通常來講不會出現什麼問題,但是對於啓動速度,咱們可以控制而且須要特別關注的地方主要有三處:性能優化

  1. Activity的onCreate流程,特別是UI的佈局與渲染操做,若是佈局過於複雜極可能致使嚴重的啓動性能問題。
  2. Application的onCreate流程,對於大型的APP來講,一般會在這裏作大量的通用組件的初始化操做。
  3. 目前有部分APP會提供自定義的啓動窗口,這裏能夠作成品牌宣傳界面或者是給用戶提供一種程序已經啓動的視覺效果。

在正式着手解決問題以前,咱們須要掌握一套正確測量評估啓動性能的方法。所幸的是,Android系統有提供一些工具來幫助咱們定位問題。微信

  1. 首先是display time:從Android KitKat版本開始,Logcat中會輸出從程序啓動到某個Activity顯示到畫面上所花費的時間。這個方法比較適合測量程序的啓動時間。
  2. 其次是reportFullyDrawn方法:咱們一般來講會使用異步懶加載的方式來提高程序畫面的顯示速度,這一般會致使的一個問題是,程序畫面已經顯示,但是內容卻還在加載中。爲了衡量這些異步加載資源所耗費的時間,咱們能夠在異步加載完畢以後調用activity.reportFullyDrawn()方法來告訴系統此時的狀態,以便獲取整個加載的耗時。
  3. 而後是Method Tracing:前面兩個方法提供了啓動耗時的總時間,但是卻沒法提供具體的耗時細節。爲了獲取具體的耗時分佈狀況,咱們可使用Method Tracing工具來進行詳細的測量。
  4. 最後是Systrace:咱們能夠在onCreate方法裏面添加trace.beginSection()與trace.endSection()方法來聲明須要跟蹤的起止位置,系統會幫忙統計中間經歷過的函數調用耗時,並輸出報表。

2. App Launch Time & Activity Creation

提高Activity的建立速度是優化APP啓動速度的首要關注目標。從桌面點擊APP圖標啓動應用開始,程序會顯示一個啓動窗口等待Activity的建立加載完畢再進行顯示。在Activity的建立加載過程當中,會執行不少的操做,例如設置頁面的主題,初始化頁面的佈局,加載圖片,獲取網絡數據,讀寫Preference等等。網絡

上述操做的任何一個環節出現性能問題均可能致使畫面不能及時顯示,影響了程序的啓動速度。上一個段落咱們介紹了使用Method Tracing來發現那些耗時佔比相對較多的方法。假設咱們發現某個方法執行時間過長,接下去就可使用Systrace來幫忙定位究竟是什麼緣由致使那個方法執行時間過長。app

除了使用工具進行具體定位分析性能問題以外,如下兩點經驗能夠幫助咱們對Activity啓動作性能優化:異步

  1. 優化佈局耗時:一個佈局層級越深,裏面包含須要加載的元素越多,就會耗費更多的初始化時間。關於佈局性能的優化,這裏就不展開描述了!
  2. 異步延遲加載:一開始只初始化最須要的佈局,異步加載圖片,非當即須要的組件能夠作延遲加載。

3. App Launch Time & Bloated Application Objects

在Application初始化的地方作太多繁重的事情是可能致使嚴重啓動性能問題的元兇之一。Application裏面的初始化操做不結束,其餘任意的程序操做都沒法進行。函數

有時候,咱們會一股腦的把絕大多數全局組件的初始化操做都放在Application的onCreate裏面,但其實不少組件是須要作區隊對待的,有些能夠作延遲加載,有些能夠放到其餘的地方作初始化操做,特別須要留意包含Disk IO操做,網絡訪問等嚴重耗時的任務,他們會嚴重阻塞程序的啓動。

優化這些問題的解決方案是作延遲加載,能夠在application裏面作延遲加載,也能夠把一些初始化的操做延遲到組件真正被調用到的時候再作加載。

4. App Launch Time & Theme Launch Screens

啓動閃屏不只僅能夠做爲品牌宣傳頁,還可以減輕用戶對啓動耗時的感知,可是若是使用不恰當,將拔苗助長。前面介紹過當點擊桌面圖標啓動APP的時候,程序會顯示一個啓動窗口,一直到頁面的渲染加載完畢。若是程序的啓動速度足夠快,咱們看的閃屏窗口停留顯示的時間則會很短,可是當程序啓動速度偏慢的時候,這個啓動閃屏能夠必定程度上減輕用戶等待的焦慮感,避免用戶過於輕易的關閉應用。

目前大多數開發者都會經過設置啓動窗口主題的方式來替換系統默認的啓動窗口,經過這種方式只是使用『障眼法』弱化了用戶對啓動時間的感知,但本質上並無對啓動速度作什麼優化。也有些APP經過關閉啓動窗口屬性android:windowDisablePreview的方式來直接移除系統默認的啓動窗口,可是這樣的弊端是用戶從點擊桌面圖標到真的看到實際頁面的這段時間當中,畫面沒有任何變化,這樣的用戶體驗是十分糟糕的!

對於啓動閃屏,正確的使用方法是自定義一張圖片,把這張圖片經過設置主題的方式顯示爲啓動閃屏,代碼執行到主頁面的onCreate的時候設置爲程序正常的主題。

5. Smaller APKs: A Checklist

減小應用程序安裝包的大小,不只僅減小了用戶的網絡數據流量還減小了下載等待的時間。毋庸置疑,儘可能減小程序安裝包的大小是十分有必要的。一般來講,減小程序安裝包的大小有兩條規律:要麼減小程序資源的大小,要麼就是減小程序的代碼量。這裏總結一個簡易版的減小安裝包大小的Checklist:

減小程序圖片資源的大小

  1. 確保在build.gradle文件中開啓了minifEnabledshrinkResources的屬性,這兩個屬性能夠幫助移除那些在程序中使用不到的代碼與資源,幫助減小APP的安裝包大小。
  2. 有選擇性的提供對應分辨率的圖片資源,系統會自動匹配最合適分辨率的圖片並執行拉伸或者壓縮的處理。
  3. 在符合條件的狀況下,使用Vertor Drawable替代傳統的PNG/JPEG圖片,可以極大的減小圖片資源的大小。傳統模式下,針對不一樣dpi的手機都須要提供一套PNG/JPEG的圖片,而若是使用Vector Drawable的話,只須要一個XML文件便可。
  4. 儘可能複用已經存在的資源圖片,使用代碼的方式對已有的資源進行復用,以下圖所示:

以上幾點雖然看起來都微不足道,可是真正執行以後,可以顯著減小安裝包的資源圖片大小。

減小程序的代碼量

  1. 開啓MinifEnabled,Proguard。打開這些編譯屬性以後,程序在打包的時候就不會把沒有引用到的代碼編譯進來,以此達到減小安裝包大小的目的。

  2. 注意由於編譯行爲額外產生的方法數,例如相似Enum,Protocal Buffer可能致使方法數與類的個數增長。

  3. 部分引入到工程中的jar類庫可能並非專門針對移動端APP而設計的,他們最開始多是運用在PC或者Server上的。使用這些類庫不只僅額外增長了包的大小,還增長了編譯時間。單純依靠Proguard可能沒法徹底移除那些使用不到的方法,最佳的方式是使用一些更加輕量化,專門爲Android APP設計的jar類庫。

安裝包的拆分

設想一下,一個low dpi,API<14的用戶手機下載安裝的APK裏面卻包含了大量xxhdpi的資源文件,對於這個用戶來講,這個APK是存在很大的資源浪費的。幸虧Android平臺爲咱們提供了拆分APK的方法,它可以根據API Level,屏幕大小以及GPU版本的不一樣進行拆分,使得對應平臺的用戶下載到最合適本身手機的安裝包。

更多關於安裝包拆分的信息,請查看Configure APK SplitsMaintaining Multiple APKs(因爲國內應用分發市場的現狀,這一條几乎沒有辦法執行)。

6. VectorDrawable for smaller APKs

針對不一樣的分辨率提供多張精度的圖片會額外增長APK的大小,針對這個問題的解決方案是考慮使用VectorDrawable,它僅僅只須要一個文件,可以動態生成對應分辨率的圖片。

VectorDrawable經過XML文件描述圖片的形狀,大小,樣式。

經過這種方式,咱們能夠顯著減小圖片資源對安裝包大小的影響。

使用VectorDrawable還能夠避免由於使用幀動畫致使的圖片資源過多的狀況,以下圖所示

前面介紹了VectorDrawable(VD)的優點,可是在使用VectorDrawable的時候,仍是有如下的問題須要特別注意的?

  • 首先VD的加載有異於JPEG/PNG文件,圖片文件能夠依靠硬件進行紋理的渲染,而VD文件須要先進行加載解析,而後纔可以進行紋理的渲染。
  • 其次VD文件適用於簡單有規則的圖片渲染,不適用於那些紋理過於複雜的圖片,這樣不只僅會過分增長描述文件的複雜度還可能沒法獲取到想要的渲染效果。
  • 最後VD文件中關於Path的描述須要儘可能簡化,複雜冗餘的Path信息不只對獲得想要的圖片沒有益處,還增長了加載渲染的難度。

做者簡介:

胡凱,騰訊 Android 工程師,熱愛開源與分享,維護 Android 官方培訓課程協做項目,關注 Android 應用性能優化的總結與分享,推崇 Android 官方最佳實踐。 我的博客:http://hukai.me Github:https://github.com/kesenhoo。


更多精彩內容歡迎關注bugly的微信公衆帳號:

騰訊 Bugly是一款專爲移動開發者打造的質量監控工具,幫助開發者快速,便捷的定位線上應用崩潰的狀況以及解決方案。智能合併功能幫助開發同窗把天天上報的數千條 Crash 根據根因合併分類,每日日報會列出影響用戶數最多的崩潰,精準定位功能幫助開發同窗定位到出問題的代碼行,實時上報能夠在發佈後快速的瞭解應用的質量狀況,適配最新的 iOS, Android 官方操做系統,鵝廠的工程師都在使用,快來加入咱們吧!

相關文章
相關標籤/搜索