Android APP效能優化(最新總結)
導語
安卓大軍浩浩蕩蕩,發展已近十個年頭,技術優化日異月新,如今Android 8.0 Oreo 都發布了,Android系統性能已經非常流暢了。但是,到了各大廠商手裡,改原始碼自定系統,使得Android原生系統變得魚龍混雜,然後到了不同層次的開發工程師手裡,因為技術水平的參差不齊,即使很多手機在跑分軟體效能非常高,開啟應用依然存在卡頓現象。另外,隨著產品內容迭代,功能越來越複雜,UI頁面也越來越豐富,也成為流暢執行的一種阻礙。綜上所述,對APP進行效能優化已成為開發者該有的一種綜合素質,也是開發者能夠完成高質量應用程式作品的保證。思考優化
本著人道主義,一切從使用者體驗的角度去思考,當我們置身處地得把自己當做使用者去玩一款應用時候,那麼都會在意什麼呢?假如正在玩一款手遊,首先一定不希望玩著玩著突然閃退,然後就是遇到畫面內容很豐富的時候不希望卡頓,其次就是耗電和耗流量不希望太嚴重,最後就是版本更新的時候安裝包希望能小一點。好了,四個方面總結如下:- 穩定(記憶體溢位、崩潰)
- 流暢(卡頓)
- 耗損(耗電、流量)
- 安裝包(APK瘦身)
一、穩定——記憶體優化
由於Android應用的沙箱機制,每個應用所分配的記憶體大小是有限度的,記憶體太低就會觸發LMK——Low Memory Killer機制,既會出現閃退現象。先搞懂java的記憶體是如何分配和回收的,問題就迎刃而解了。 相關文章: 知道記憶體是如何分配和記憶體回收機制後,就算對記憶體優化有一點的認識和掌握了。使用分析工具
- Memory Monitor 工具:
- Memory Analyzer工具:
MAT 是一個快速,功能豐富的 Java Heap 分析工具,通過分析 Java 程序的記憶體快照 HPROF 分析,從眾多的物件中分析,快速計算出在記憶體中物件佔用的大小,檢視哪些物件不能被垃圾收集器回收,並可以通過檢視直觀地檢視可能造成這種結果的物件。
- LeakCanary工具:
- Android Lint 工具:
穩定性建議
影響穩定性的原因很多,比如記憶體使用不合理、程式碼異常場景考慮不周全、程式碼邏輯不合理等,都會對應用的穩定性造成影響。其中最常見的兩個場景是:Crash 和 ANR,這兩個錯誤將會使得程式無法使用。所以做好Crash監控,把崩潰資訊、異常資訊收集記錄起來,以便後續分析;合理使用主執行緒處理業務,不要在主執行緒中做耗時操作,防止ANR程式無響應發生。二、流暢——互動優化
互動是與使用者體驗最直接的方面,互動場景大概分為四個部分:UI 繪製、應用啟動、頁面跳轉、事件響應,如圖:四個方面大致歸為如下兩類:
- 介面繪製:主要原因是繪製的層級深、頁面複雜、重新整理不合理,由於這些原因導致卡頓的場景更多出現在 UI 和啟動後的初始介面以及跳轉到頁面的繪製上。
- 資料處理:導致這種卡頓場景的原因是資料處理量太大,一般分為三種情況,一是資料在處理 UI 執行緒,二是資料處理佔用 CPU 高,導致主執行緒拿不到時間片,三是記憶體增加導致 GC 頻繁,從而引起卡頓。
總結原因:我們知道Android的繪製步驟是::Measure、Layout、Draw,所以佈局的層級越深、元素越多、耗時也就越長。還有就是Android 系統每隔 16ms 發出 VSYNC 訊號,觸發對 UI 進行渲染,如果每次渲染都成功,這樣就能夠達到流暢的畫面所需的 60FPS。如果某個操作花費的時間是 24ms ,系統在得到 VSYNC 訊號時就無法正常進行正常渲染,這樣就發生了丟幀現象。那麼使用者在 32ms 內看到的會是同一幀畫面,無法在 16ms 完成渲染,最終引起重新整理不及時。兩個根本原因:
-
繪製任務太重,繪製一幀內容耗時太長。
-
主執行緒太忙,根據系統傳遞過來的 VSYNC 訊號來時還沒準備好資料導致丟幀。
建議1:佈局優化
在Android種系統對View進行測量、佈局和繪製時,都是通過對View數的遍歷來進行操作的。如果一個View數的高度太高就會嚴重影響測量、佈局和繪製的速度。Google也在其API文件中建議View高度不宜哦過10層。現在版本種Google使用RelativeLayout替代LineraLayout作為預設根佈局,目的就是降低LineraLayout巢狀產生布局樹的高度,從而提高UI渲染的效率。- 佈局複用,使用<include>標籤重用layout;
- 提高顯示速度,使用<ViewStub>延遲View載入;
- 減少層級,使用<merge>標籤替換父級佈局;
-
注意使用wrap_content,會增加measure計算成本;
-
刪除控制元件中無用屬性;
建議2:繪製優化
過度繪製是指在螢幕上的某個畫素在同一幀的時間內被繪製了多次。在多層次重疊的 UI 結構中,如果不可見的 UI 也在做繪製的操作,就會導致某些畫素區域被繪製了多次,從而浪費了多餘的 CPU 以及 GPU 資源。所以避免過度繪製:-
佈局上的優化。移除 XML 中非必須的背景,移除 Window 預設的背景、按需顯示佔位背景圖片
-
自定義View優化。使用 canvas.clipRect()來幫助系統識別那些可見的區域,只有在這個區域內才會被繪製。
建議3:啟動優化
UI 佈局。應用一般都有閃屏頁,優化閃屏頁的 UI 佈局,可以通過 Profile GPU Rendering 檢測丟幀情況。
啟動載入邏輯優化。可以採用分佈載入、非同步載入、延期載入策略來提高應用啟動速度。
資料準備。資料初始化分析,載入資料可以考慮用執行緒初始化等策略。
建議4:重新整理優化
- 減少重新整理次數;
- 縮小重新整理區域;
建議5:動畫優化
- 在實現動畫效果時,需要根據不同場景選擇合適的動畫框架來實現。有些情況下,可以用硬體加速方式來提供流暢度。
三、節省——耗電優化
在移動裝置中,電池的重要性不言而喻,沒有電什麼都幹不成。對於作業系統和裝置開發商來說,耗電優化一致沒有停止,去追求更長的待機時間,而對於一款應用來說,並不是可以忽略電量使用問題,特別是那些被歸為“電池殺手”的應用,最終的結果是被解除安裝。因此,應用開發者在實現需求的同時,需要儘量減少電量的消耗。
在 Android5.0 以前,在應用中測試電量消耗比較麻煩,也不準確,5.0 之後專門引入了一個獲取裝置上電量消耗資訊的 API:Battery Historian。Battery Historian 是一款由 Google 提供的 Android 系統電量分析工具,和Systrace 一樣,是一款圖形化資料分析工具,直觀地展示出手機的電量消耗過程,通過輸入電量分析檔案,顯示消耗情況,最後提供一些可供參考電量優化的方法。
除此之外,還有一些常用方案可提供:
-
計算優化,避開浮點運算等。
-
避免 WaleLock 使用不當。
-
使用 Job Scheduler。
四、APK瘦身
應用安裝包大小對應用使用沒有影響,但應用的安裝包越大,使用者下載的門檻越高,特別是在行動網路情況下,使用者在下載應用時,對安裝包大小的要求更高,因此,減小安裝包大小可以讓更多使用者願意下載和體驗產品。
常用應用安裝包的構成,如圖所示:
從圖中我們可以看到:
-
assets資料夾。存放一些配置檔案、資原始檔,assets不會自動生成對應的 ID,而是通過 AssetManager 類的介面獲取。
-
res。res 是 resource 的縮寫,這個目錄存放資原始檔,會自動生成對應的 ID 並對映到 .R 檔案中,訪問直接使用資源 ID。
-
META-INF。儲存應用的簽名信息,簽名信息可以驗證 APK 檔案的完整性。
-
AndroidManifest.xml。這個檔案用來描述 Android 應用的配置資訊,一些元件的註冊資訊、可使用許可權等。
-
classes.dex。Dalvik 位元組碼程式,讓 Dalvik 虛擬機器可執行,一般情況下,Android 應用在打包時通過 Android SDK 中的 dx 工具將 Java 位元組碼轉換為 Dalvik 位元組碼。
-
resources.arsc。記錄著資原始檔和資源 ID 之間的對映關係,用來根據資源 ID 尋找資源。
減少安裝包大小的常用方案
-
程式碼混淆。使用proGuard 程式碼混淆器工具,它包括壓縮、優化、混淆等功能。
-
資源優化。比如使用 Android Lint 刪除冗餘資源,資原始檔最少化等。
-
圖片優化。比如利用 AAPT 工具對 PNG 格式的圖片做壓縮處理,降低圖片色彩位數等。
-
避免重複功能的庫,使用 WebP圖片格式等。
-
外掛化。比如功能模組放在伺服器上,按需下載,可以減少安裝包大小。
小結:
最後說一句,效能優化是一個非常具有挑戰性的工作,上面列出很多分析記憶體、優化記憶體的方法,但是真正優化工作遠不止這麼簡單,這裡只是列舉了一些入門的方法,而要進行完美的記憶體優化、記憶體分析絕非一日之功,需要開發者深厚的技術功底合耐心。