Android性能優化典范 - 第6季

導語

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

1. App Launch time 101

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

從技術角度來說,當用戶點擊桌面圖標開始,系統會立即為這個APP創建獨立的專屬進程,然后顯示啟動窗口,直到APP在自己的進程里面完成了程序的創建以及主線程完成了Activity的初始化顯示操作,再然后系統進程就會把啟動窗口替換成APP的顯示窗口。

上述流程里面的絕大多數步驟都是由系統控制的,一般來說不會出現什么問題,可是對于啟動速度,我們能夠控制并且需要特別關注的地方主要有三處:

  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來幫忙定位到底是什么原因導致那個方法執行時間過長。

除了使用工具進行具體定位分析性能問題之外,以下兩點經驗可以幫助我們對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文件中開啟了 minifEnabled 與 shrinkResources 的屬性,這兩個屬性可以幫助移除那些在程序中使用不到的代碼與資源,幫助減少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版本的不同進行拆分,使得對應平臺的用戶下載到最合適自己手機的安裝包。

6. VectorDrawable for smaller APKs

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

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

通過這種方式,我們可以顯著減少圖片資源對安裝包大小的影響。

使用VectorDrawable還可以避免因為使用幀動畫導致的圖片資源過多的情況,如下圖所示

前面介紹了VectorDrawable(VD)的優勢,但是在使用VectorDrawable的時候,還是有以下的問題需要特別注意的?

  • 首先VD的加載有異于JPEG/PNG文件,圖片文件可以依靠硬件進行紋理的渲染,而VD文件需要先進行加載解析,然后才能夠進行紋理的渲染。

  • 其次VD文件適用于簡單有規則的圖片渲染,不適用于那些紋理過于復雜的圖片,這樣不僅僅會過度增加描述文件的復雜度還可能無法獲取到想要的渲染效果。

??????????????

  • 最后VD文件中關于Path的描述需要盡量簡化,復雜冗余的Path信息不僅對得到想要的圖片沒有益處,還增加了加載渲染的難度

???????

 

 

來自:http://dev.qq.com/topic/580d91208d80e49771f0a07c

 

 本文由用戶 DorthyShea 自行上傳分享,僅供網友學習交流。所有權歸原作者,若您的權利被侵害,請聯系管理員。
 轉載本站原創文章,請注明出處,并保留原始鏈接、圖片水印。
 本站是一個以用戶分享為主的開源技術平臺,歡迎各類分享!