1. 程式人生 > >Android 效能優化典範(六)

Android 效能優化典範(六)

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

1)App Launch time 101

提高程式的啟動速度意義重大,很顯然,啟動時間越短,使用者才越有耐心等待開啟這個 App 進行使用。反之啟動時間越長,使用者則越有可能來不及等到 App 開啟就已經切換到其他 App 了。程式啟動過程中的那些複雜錯誤的操作很可能導致嚴重的效能問題。

Android 系統會根據使用者的操作行為調整程式的顯示策略,用來提高程式的顯示效能。例如,一旦使用者點選桌面圖示,Android 系統會立即顯示一個啟動視窗,這個視窗會一直保持顯示,直到畫面中的元素成功載入並繪製完第一幀。這種行為常見於程式的冷啟動,或者程式的熱啟動場景(程式從後臺被喚起或者從其他 App 介面切換回來)。那麼關鍵的問題是,使用者很可能會因為從啟動視窗到顯示畫面的過程耗時過長而感到厭煩,從而導致使用者沒有來得及等程式啟動完畢就切換到其他 App 了。更嚴重的是,如果啟動時間過長,可能導致程式出現 ANR。我們應該避免出現這兩種糟糕的情況。

從技術角度來說,當用戶點選桌面圖示開始,系統會立即為這個 App 建立獨立的專屬程序,然後顯示啟動視窗,直到 App 在自己的程序裡面完成了程式的建立以及主執行緒完成了 Activity 的初始化顯示操作,再然後系統程序就會把啟動視窗替換成APP的顯示視窗。

android_perf_6_launch_time_start_process

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

  1. Activity 的 onCreate 流程,特別是 UI 的佈局與渲染操作,如果佈局過於複雜很可能導致嚴重的啟動效能問題。
  2. Application 的 onCreate 流程,對於大型的 App 來說,通常會在這裡做大量的通用元件的初始化操作。
  3. 目前有部分 App 會提供自定義的啟動視窗,這裡可以做成品牌宣傳介面或者是給使用者提供一種程式已經啟動的視覺效果。

在正式著手解決問題之前,我們需要掌握一套正確測量評估啟動效能的方法。所幸的是,Android 系統有提供一些工具來幫助我們定位問題。

1. 首先是 display time:從 Android KitKat 版本開始,Logcat 中會輸出從程式啟動到某個 Activity 顯示到畫面上所花費的時間。這個方法比較適合測量程式的啟動時間。

android_perf_6_launch_time_display_time

2. 其次是 reportFullyDrawn 方法:我們通常來說會使用非同步懶載入的方式來提升程式畫面的顯示速度,這通常會導致的一個問題是,程式畫面已經顯示,可是內容卻還在載入中。為了衡量這些非同步載入資源所耗費的時間,我們可以在非同步載入完畢之後呼叫activity.reportFullyDrawn()方法來告訴系統此時的狀態,以便獲取整個載入的耗時。

android_perf_6_launch_time_report_fully_drawn

3. 然後是 Method Tracing:前面兩個方法提供了啟動耗時的總時間,可是卻無法提供具體的耗時細節。為了獲取具體的耗時分佈情況,我們可以使用 Method Tracing工具來進行詳細的測量。

android_perf_6_launch_time_method_tracing

4. 最後是 Systrace:我們可以在 onCreate 方法裡面新增trace.beginSection()trace.endSection()方法來宣告需要跟蹤的起止位置,系統會幫忙統計中間經歷過的函式呼叫耗時,並輸出報表。

android_perf_6_launch_time_systrace

2)App Launch Time & Activity Creation

提升 Activity 的建立速度是優化 App 啟動速度的首要關注目標。從桌面點選 App 圖示啟動應用開始,程式會顯示一個啟動視窗等待 Activity 的建立載入完畢再進行顯示。在 Activity 的建立載入過程中,會執行很多的操作,例如設定頁面的主題、初始化頁面的佈局、載入圖片、獲取網路資料、讀寫 Preference 等。

android_perf_6_activity_creation_0

上述操作的任何一個環節出現效能問題都可能導致畫面不能及時顯示,影響了程式的啟動速度。上一個段落我們介紹了使用 Method Tracing 來發現那些耗時佔比相對較多的方法。假設發現某個方法執行時間過長,接下去就可以使用 Systrace 來幫忙定位到底是什麼原因導致那個方法執行時間過長。

除了使用工具進行具體定位分析效能問題之外,以下兩點經驗可以幫助我們對 Activity 啟動做效能優化:

  1. 優化佈局耗時:一個佈局層級越深,裡面包含需要載入的元素越多,就會耗費更多的初始化時間。關於佈局效能的優化,這裡就不展開描述了。
  2. 非同步延遲載入:一開始只初始化最需要的佈局,非同步載入圖片,非立即需要的元件可以做延遲載入。

3)App Launch Time & Bloated Application Objects

在 Application 初始化的地方做太多繁重的事情是可能導致嚴重啟動效能問題的元凶之一。Application 裡面的初始化操作不結束,其他任意的程式操作都無法進行。

android_perf_6_application_objs

有時候,我們會一股腦地把絕大多數全域性元件的初始化操作都放在 Application 的onCreate裡面,但其實很多元件是需要做區別對待的,有些可以做延遲載入,有些可以放到其他的地方做初始化操作,特別需要留意包含 Disk IO 操作、網路訪問等嚴重耗時的任務,它們會嚴重阻塞程式的啟動。

android_perf_6_application_create

優化這些問題的解決方案是做延遲載入,可以在 Application 裡面做延遲載入,也可以把一些初始化的操作延遲到元件真正被呼叫到的時候再做載入。

android_perf_6_application_lazyload

4)App Launch Time & Theme Launch Screens

啟動閃屏不僅僅可以作為品牌宣傳頁,還能夠減輕使用者對啟動耗時的感知,但是如果使用不當,將適得其反。前面介紹過當點選桌面圖示啟動 App 的時候,程式會顯示一個啟動視窗,一直到頁面的渲染載入完畢。如果程式的啟動速度足夠快,我們看到的閃屏視窗停留顯示的時間則會很短,但是當程式啟動速度偏慢的時候,這個啟動閃屏可以一定程度上減輕使用者等待的焦慮感,避免使用者過於輕易的關閉應用。

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

android_perf_6_launch_screen
android_perf_6_launch_screen2

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

android_perf_6_launch_screen3
android_perf_6_launch_screen4

5)Smaller APKs: A Checklist

減少應用程式安裝包的大小,不僅僅減少了使用者的網路資料流量還減少了下載等待的時間。毋庸置疑,儘量減少程式安裝包的大小是十分有必要的。通常來說,減少程式安裝包的大小有兩條規律:要麼減少程式資源的大小,要麼就是減少程式的程式碼量。這裡總結一個簡易版的減少安裝包大小的 Checklist。

減少程式圖片資源的大小

1. 確保在 build.gradle 檔案中開啟了minifEnabledshrinkResources的屬性,這兩個屬性可以幫助移除那些在程式中使用不到的程式碼與資源,幫助減少 App 的安裝包大小。

android_perf_6_smaller_apks_gradle

2. 有選擇性的提供對應解析度的圖片資源,系統會自動匹配最合適解析度的圖片並執行拉伸或者壓縮的處理。

android_perf_6_smaller_apks_dpi

3. 在符合條件的情況下,使用 Vertor Drawable 替代傳統的 PNG/JPEG 圖片,能夠極大地減少圖片資源的大小。傳統模式下,針對不同 dpi 的手機都需要提供一套 PNG/JPEG 的圖片,而如果使用 Vector Drawable 的話,只需要一個 XML 檔案即可。

android_perf_6_smaller_apks_vector

4. 儘量複用已經存在的資源圖片,使用程式碼的方式對已有的資源進行復用,如下圖所示:

android_perf_6_smaller_apks_reuse

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

減少程式的程式碼量

  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 版本的不同進行拆分,使得對應平臺的使用者下載到最合適自己手機的安裝包。

android_perf_6_smaller_apks_split

6)VectorDrawable for smaller APKs

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

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

android_perf_6_vectordrawable_origin

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

android_perf_6_vectordrawable_dpi
android_perf_6_vectordrawable_dpi2

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

android_perf_6_vectordrawable_animation

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

  • 首先 VD 的載入有異於 JPEG/PNG 檔案,圖片檔案可以依靠硬體進行紋理的渲染,而 VD 檔案需要先進行載入解析,然後才能夠進行紋理的渲染。
android_perf_6_vectordrawable_load
  • 其次 VD 檔案適用於簡單有規則的圖片渲染,不適用於那些紋理過於複雜的圖片,這樣不僅僅會過度增加描述檔案的複雜度還可能無法獲取到想要的渲染效果。
android_perf_6_vectordrawable_simple
  • 最後,VD 檔案中關於 Path 的描述需要儘量簡化,複雜冗餘的 Path 資訊不僅對得到想要的圖片沒有益處,還增加了載入渲染的難度。
android_perf_6_vectordrawable_path

相關推薦

Android 效能優化典範

這裡是Android效能優化典範第 6 季的課程學習筆記,從被@知會到有連載更新,這篇學習筆記就一直被惦記著。現在學習記錄分享一下,請多多指教包涵!這次一共才 6 個小段落,涉及的內容主要有程式啟動時間效能優化的三個方面:優化 activity 的建立過程,優化 App

Android效能優化典範

來源 http://www.csdn.net/article/2015-04-29/2824583-android-performance-patterns-season-2/4 Google前幾天剛釋出了Android效能優化典範第2季的 課程,一共20個短視訊,包括的內

Android效能優化典範

Android效能優化典範的課程最近更新到第三季了,這次一共12個短視訊課程,包括的內容大致有:更高效的ArrayMap容器,使用Android系統提供的特殊容器來避免自動裝箱,避免使用列舉型別,注意onLowMemory與onTrimMemory的回撥,避免記憶體洩漏,

Android 效能優化典範電量優化|網路優化JobSchedule使用|圖片壓縮快取| StictMode

1) Battery Drain and Networking對於手機程式,網路操作相對來說是比較耗電的行為。優化網路操作能夠顯著節約電量的消耗。在效能優化第1季裡面有提到過,手機硬體的各個模組的耗電量是不一樣的,其中移動蜂窩模組對電量消耗是比較大的,另外蜂窩模組在不同工作強度下,對電量的消耗也是有差異的。當

Android效能優化典範過度繪製

前言        本文轉載於資深工程師胡凱的文章,在此對其表示感謝,在文章學習到很多關於效能優化問題,胡凱的部落格主頁點選連結,本人轉載的目的是為了更加方便學習,在轉載的同時本人會對自已認為好的地方進行重點著色,以及新增一些簡單示例的實現,對於一些需要更新的在此新增連結關聯

Android效能優化典範

這是Android效能優化典範第5季的課程學習筆記,拖拖拉拉很久,記錄分享給大家,請多多包涵、擔待指正!文章共有10個段落,涉及的內容有:多執行緒併發的效能問題,介紹了AsyncTask、HandlerThread、IntentService與ThreadPool分別適合

【朝花夕拾】Android效能篇之Android程序管理機制

一、Android程序管理的特殊設計        Linux系統對程序的管理方式是一旦程序活動停止,系統就會結束該程序。儘管Android基於Linux Kernel,但在程序管理上,卻採取了另外一種獨特的設計:當程序活動停止時,系統並不會立刻結束它,而是會盡可能地將該程序儲存在記憶體中,在以後的某個時間,

Android效能優化筆記——啟動優化

參考文章:  https://time.geekbang.org/column/article/73651 https://mp.weixin.qq.com/s/eaArt5Udc4WZ3NoH5RlEkQ https://juejin.im/post/5874bff0128fe1006b4

Android效能優化——佈局優化

                                                 Android效能優化篇 題記: 不知道別人是怎麼學習的,我總是覺得我學習的效率很低,昨天發生了不愉快的事情後,我痛定思痛,反思了一下自己,還是總結不夠,也是工作中接觸的東西

Android效能優化十 一篇---卡頓分析,正確評測流暢度

一、FPS評測應用流暢度不準確 說到應用的流暢度,都會想到FPS,系統獲取FPS的原理是:手機螢幕顯示的內容是通過Android系統的SurfaceFLinger類,把當前系統裡所有程序需要顯示的資訊合成一幀,然後提交到螢幕上進行顯示,FPS就是1秒內Surf

常見數據庫優化方案

nbsp ref div wpa update title get 殺死 upd 數據庫密碼重置 skip-grant-tables:非常有用的mysql啟動參數(不啟動grant-tables授權表) skip-grant-tables:非常有用

Android項目實戰:JazzyGridView和JazzyListView的使用

@+ java類 gif HR 使用 out tar 項目 適配器 原文:Android項目實戰(六):JazzyGridView和JazzyListView的使用GridView和ListView控件劃動的動畫效果 ---------------------------

【朝花夕拾】Android效能篇之序言及JVM

序言        筆者從事Anroid開發有些年頭了,深知掌握Anroid效能優化方面的知識的必要性,這是一個程式設計師必須修煉的內功。在面試中,它是面試官的摯愛,在工作中,它是程式碼質量的攔路虎,其重要性可見一斑。在團隊中,效能優化的工作又往往由經驗豐富的老師傅來

35 個 Java 程式碼效能優化總結

前言 程式碼優化,一個很重要的課題。可能有些人覺得沒用,一些細小的地方有什麼好修改的,改與不改對於程式碼的執行效率有什麼影響呢?這個問題我是這麼考慮的,就像大海里面的鯨魚一樣,它吃一條小蝦米有用嗎?沒用,但是,吃的小蝦米一多之後,鯨魚就被餵飽了。程式碼優化也是一樣,如果專案著眼於儘快無BUG

Android自助餐之JniNDK入門

Android自助餐之Jni(六)NDK入門 Android自助餐之Jni六NDK入門 Android自助餐專欄 Android自助餐之Jni一最簡單的執行 Android自助

效能優化措施JAVA

一 前端效能優化 1.頁面的HTTP請求數量 2.使用CDN網路 3.是否使用壓縮,對於前段樣式檔案與指令碼檔案,可將其中空格、註釋等不必要的字元去掉,並且通過使用gzip壓縮來減少網路上傳輸的位元組數。 二 java程式優化 1.使用單例,如餓漢 2.futur

AndroidAndroid Studio的使用--如何更新Android Studio

一、前文 Android Studio系列文章,主要講解如何使用這個IDE,原文釋出與部落格園,請多多支援原作者。 二、原文 原文出處: 部落格園 原文作者: StephenHe 原文連結: https://www.cnblogs.com/begin1949/p/496660

Android效能優化典範 - 第4季

Android效能優化典範 - 第4季 DEC 31ST, 2015 | COMMENTS Android效能優化典範第4季的課程學習筆記終於在2015年的最後一天完成了,文章共17個段落,包含的內容大致有:優化網路請求的行為,優化安裝包的資原始檔,優化資料

Spring+SpringMVC+MyBatis+easyUI整合優化easyUI與富文字編輯器UEditor整合

日常囉嗦 本來這一篇和接下來的幾篇是打算講一下JDBC和資料庫優化的,但是最近很多朋友加我好友也討論了一些問題,我發現大家似乎都是拿這個專案作為練手專案,作為腳手架來用的,因此呢,改變了一下思路,JDBC和資料庫優化這一塊兒延後一點再去說,先豐富一下專案的頁面

如何做Go的效能優化

Go的效能優化其實總的來說和C/C++等這些都差不多,但也有它自己獨有的排查方法和陷阱,這些都來源於它的語言特性和環境。 1.效能優化前提——任何好的東西都是在正確的前提上 程式碼界的很多事是和我們生活的哲學息息相關的,我們想要做好一件事,首先要保證我們能按時完成我們的任務,其次再去想如何把工作做的更好。