android APP性能優化

前述

最近在作app性能優化,這裏作一個總結,供你們瞭解學習,也方便本身之後查閱.
用android的同窗都知道,新買的手機用過一段時間後,手機變得愈來愈卡了;裝了一些APP後,電量用得飛快,一天基本要一充;有些APP打開半天加載不出來;有些APP進入某些頁面忽然閃退;還有用了一些APP,流量用得飛快,幾百M的流量用了幾天就沒有了等等;html

這是什麼緣由呢?
  • android系統源碼是開放的,能夠對源碼的更改,像國內的幾大手機廠商,都是對系統進入定製開發,這樣就會引起一系列問題,好比說著名的系統碎片化問題;
  • 各大廠商定製的系統,兼容性確定很差,開發人員要對各個系統作各類適配,還有開發人員的水平參次不齊,開發出來的APP就會出現這樣那樣的問題等等;
那咱們又得如何處理這樣的問題呢?

那就是今天咱們要說的APP性能優化,開發人員開發出來的app要性能好,用戶體驗好,性能好的APP總結一下,有以下幾點:android

  • APP使用起來不卡頓,要流暢;
  • 要省電,省流量;
  • 要穩定,不閃退(減小閃退,ANR率);
  • APP包儘可能要小;

要開發性能好的app,主要要達到以上四點;可是如何達到上面幾點呢,那咱們得找到達不到的緣由,下面咱們一一來分析,並給出解決方案:git

卡頓優化

Android 應用啓動慢,使用時常常卡頓,是很是影響用戶體驗的,應該儘可能避免出現。總的來講形成卡頓的緣由有以下幾種:github

  • UI的繪製。主要緣由是繪製的層級深、頁面複雜、刷新不合理,因爲這些緣由致使卡頓的場景更多出如今 UI 和啓動後的初始界面以及跳轉到頁面的繪製上。
  • 數據處理上。致使這種卡頓場景的緣由是數據處理量太大,通常分爲三種狀況,一是數據在主線程處理,這個是初級工程師會犯的錯誤,二是數據處理佔用 CPU 高,致使主線程拿不到時間片,三是內存增長致使 GC 頻繁,從而引發卡頓。引發卡頓的緣由不少,但無論怎麼樣的緣由和場景,最終都是經過設備屏幕上顯示來達到用戶,歸根到底就是顯示有問題,因此,要解決卡頓,就要先了解 Android 系統的渲染機制。
  • UI的過分繪製,繪製的頁面有幾層View,底層View都是隱藏的,這種的還繪製的話就會形成過分繪製
andriod的渲染機制

要在屏幕上顯示,其實要通過一系列的過程,Android 應用程序把通過測量、佈局、繪製後的 surface 緩存數據,經過 SurfaceFlinger 把數據渲染到顯示屏幕上, 經過 Android 的刷新機制來刷新數據。也就是說應用層負責繪製,系統層負責渲染,經過進程間通訊把應用層須要繪製的數據傳遞到系統層服務,系統層服務經過刷新機制把數據更新到屏幕上。web

這裏咱們先介紹一個名詞:FPS。FPS 表示每秒傳遞的幀數。在理想狀況下,60 FPS 就感受不到卡,這意味着每一個繪製時長應該在16 ms 之內。可是 Android 系統頗有可能沒法及時完成那些複雜的頁面渲染操做。Android 系統每隔 16ms 發出 VSYNC 信號,觸發對 UI 進行渲染,若是每次渲染都成功,這樣就可以達到流暢的畫面所需的 60FPS。若是某個操做花費的時間是 24ms ,系統在獲得 VSYNC 信號時就沒法正常進行正常渲染,這樣就發生了丟幀現象。那麼用戶在 32ms 內看到的會是同一幀畫面,這種現象在執行動畫或滑動列表比較常見,還有多是你的 Layout 太過複雜,層疊太多的繪製單元,沒法在 16ms 完成渲染,最終引發刷新不及時。json

android的View的繪製流程你們應該都知道,都是要通過三大核心步驟:Measure、Layout、Draw。具體是如何實現的建議看一下View的源碼,這裏我就很少說了;若是繪製的層級深,頁面複雜,在Measure、Layout這二個步驟要花費大量的時間;這樣也會造卡頓現象;canvas

andriod卡頓優化方案
  • 不要在主線程進行網絡訪問/大文件的IO操做
  • 繪製UI時,儘可能減小繪製UI層次;減小沒必要要的view嵌套,能夠用Hierarchy Viewer工具來檢測,後面會詳細講;
  • 當咱們的佈局是用的FrameLayout的時候,咱們能夠把它改爲merge,能夠避免本身的幀佈局和系統的ContentFrameLayout幀佈局重疊形成重複計算(measure和layout)
  • 提升顯示速度,使用ViewStub:當加載的時候纔會佔用。不加載的時候就是隱藏的,僅僅佔用位置。
  • 在view層級相同的狀況下,儘可能使用 LinerLayout而不是RelativeLayout;由於RelativeLayout在測量的時候會測量二次,而LinerLayout測量一次,能夠看下它們的源碼;
  • 刪除控件中無用的屬性;
  • 佈局複用.好比listView 佈局複用
  • 儘可能避免過分繪製(overdraw),好比:背景常常容易形成過分繪製。因爲咱們佈局設置了背景,同時用到的MaterialDesign的主題會默認給一個背景。這時應該把主題添加的背景去掉;還有移除 XML 中非必須的背景
  • 自定義View優化。使用 canvas.clipRect()來幫助系統識別那些可見的區域,只有在這個區域內纔會被繪製。也是避免過分繪製.
  • 啓動優化,啓動速度的監控,發現影響啓動速度的問題所在,優化啓動邏輯,提升應用的啓動速度。好比閃屏頁面,合理優化佈局,加載邏輯優化,數據準備,這裏後面我會單獨寫一篇文章講如何優化程序的啓動速度及Splash頁面設計,這裏還會講到熱啓動和冷啓動.
  • 合理的刷新機制,儘可能減小刷新次數,儘可能避免後臺有高的 CPU 線程運行,縮小刷新區域。
andriod卡頓優化所用到的工具

性能問題並不容易復現,也很差定位,可是真的碰到問題就須要藉助相應的的調試工具,下面介紹比較經常使用的調試工具。緩存

  • 1.Profile GPU Rendering
    在手機開發者模式下,有一個卡頓檢測工具叫作:Profile GPU Rendering,看圖:
image.png

上圖中的綠線表明16ms,要確保一秒內打到60fps,你須要確保這些幀的每一條線都在綠色的16ms標記線之下.任什麼時候候你看到一個豎線超過了綠色的標記現,你就會看到你的動畫有卡頓現象產生.性能優化

下面的柱狀圖藍色表明測量繪製的時間,當你看到藍色的線很高的時候,有多是由於你的一堆視圖忽然變得無效了(即須要從新繪製),或者你的幾個自定義視圖的onDraw函數過於複雜.微信

柱狀圖紅色表明執行的時間,這部分是Android進行2D渲染 Display List的時間,爲了繪製到屏幕上,Android須要使用OpenGl ES的API接口來繪製Display List.這些API有效地將數據發送到GPU,最終在屏幕上顯示出來.當你看到紅色的線很是高的時候,這些複雜的自定義View就是罪魁禍首:

橙色部分表示的是處理時間,或者說是CPU告訴GPU渲染一幀的地方,這是一個阻塞調用,由於CPU會一直等待GPU發出接到命令的回覆,若是柱狀圖很高,那就意味着你給GPU太多的工做,太多的負責視圖須要OpenGL命令去繪製和處理.

總之,保持動畫流暢的關鍵就在於讓這些垂直的柱狀條儘量地保持在綠線下面,任什麼時候候超過綠線,你就有可能丟失一幀的內容.

  • 2.Debug GPU overDraw過分繪製檢測
    在手機開發者模式下,有一個過分繪製檢測工具叫作:Debug GPU overDraw,看圖:
    image.png

    image.png

原色:沒有過分繪製
藍色:1 次過分繪製
綠色:2 次過分繪製
粉色:3 次過分繪製
紅色:4 次及以上過分繪製

耗電優化

在移動設備中,電池的重要性不言而喻,沒有電什麼都幹不成。對於操做系統和設備開發商來講,耗電優化一致沒有中止,去追求更長的待機時間,而對於一款應用來講,並非能夠忽略電量使用問題,特別是那些被歸爲「電池殺手」的應用,最終的結果是被卸載。所以,應用開發者在實現需求的同時,須要儘可能減小電量的消耗。
耗電的緣由其實不少,這裏我就講一下幾種優化方案,優化方案的反面就是他的緣由了,幾種優化方案以下:

  • 合理的使用wack_lock鎖,wake_lock鎖主要是相對系統的休眠(這裏就是爲了省電,才作休)而言的,意思就是個人程序給CPU加了這個鎖那系統就不會休眠了,這樣作的目的是爲了全力配合咱們程序的運行。有的狀況若是不這麼作就會出現一些問題,好比微信等及時通信的心跳包會在熄屏不久後中止網絡訪問等問題。因此微信裏面是有大量使用到了wake_lock鎖。這裏有一篇關於wake_lock的使用,請查閱

  • 使用jobScheduler2,集中處理一些網絡請求,有些不用很及時的處理能夠放在充電的時候處理,好比,圖片的處理,APP下載更新等等,這裏有一篇關於jobScheduler的使用,請查閱

  • 計算優化,避開浮點運算等。

  • 數據在網絡上傳輸時,儘可能壓縮數據後再傳輸,建議用FlatBuffer序列化技術,這個比json效率高不少倍,不瞭解FlatBuffer,建議找資料學習一下,後面有時間的話,也會專門寫關於FlatBuffer的文章.

andriod耗電分析所用到的工具

在 Android5.0 之前,在應用中測試電量消耗比較麻煩,也不許確,5.0 以後專門引入了一個獲取設備上電量消耗信息的 API:Battery Historian。Battery Historian 是一款由 Google 提供的 Android 系統電量分析工具,是一款圖形化數據分析工具,直觀地展現出手機的電量消耗過程,經過輸入電量分析文件,顯示消耗狀況,最後提供一些可供參考電量優化的方法。

  • Battery Historian耗電分析工具
    image.png

Battery Historian耗電分析工具的開源地址;具體如何使用這裏不細講,之後單獨寫文章介紹;

安裝包大小優化

隨着功能不斷增長,APP的包確定不會斷的變大,但應用的安裝包越大,用戶下載的門檻越高,特別是在移動網絡狀況下,用戶在下載應用時,對安裝包大小的要求更高,所以,減少安裝包大小可讓更多用戶願意下載和體驗產品。因此,咱們仍是要想辦法去如何去優化,儘可能減少app的安排包.

APP包優化方案
  • res資源優化
    (1)只使用一套圖片,使用高分辨率的圖片。
    (2)UI設計在ps安裝TinyPNG插件,對圖片進行無損壓縮。
    (3)svg圖片:一些圖片的描述,犧牲CPU的計算能力的,節省空間。使用的原則:簡單的圖標。
    (4)圖片使用WebP(developers.google.com/speed/webp/)的格式(Facebook、騰訊、淘寶在用。)缺點:加載相比於PNG要慢不少。 可是配置比較高。工具:isparta.github.io/
    (5)使用tintcolor(android - Change drawable color programmatically)實現按鈕反選效果。
  • 代碼優化
    (1)實現功能模塊的邏輯簡化
    (2)Lint工具檢查無用文件將無用的資源列在「UnusedResources: Unused resources」,刪除。
    (3)移除無用的依賴庫。
  • lib資源優化
    (1)動態下載的資源。
    (2)一些模塊的插件化動態添加。
    (3)so文件的剪裁和壓縮。
  • assets資源優化
    (1)音頻文件最好使用有損壓縮的格式,好比採用opus、mp3等格式,可是最好不要使用無損壓縮的音樂格式
    (2)對ttf字體文件壓縮,能夠採用FontCreator工具只提取出你須要的文字。好比在作日期顯示時,其實只須要數字字體,可是使用原有的字體庫可能須要10MB大小,若是隻是把你須要的字體提取出來生成的字體文件只有10KB
  • 代碼混淆。
    使用proGuard 代碼混淆器工具,它包括壓縮、優化、混淆等功能。
  • 7z極限壓縮
    具體請參考微信的安接包壓縮,實現實現原理,有時間再分析;

內存優化

在 Android 系統中有個垃圾內存回收機制,在虛擬機層自動分配和釋放內存,所以不須要在代碼中分配和釋放某一塊內存,從應用層面上不容易出現內存泄漏和內存溢出等問題,可是須要內存管理。Android 系統在內存管理上有一個 Generational Heap Memory 模型,內存回收的大部分壓力不須要應用層關心, Generational Heap Memory 有本身一套管理機制,當內存達到一個閾值時,系統會根據不一樣的規則自動釋放系統認爲能夠釋放的內存,也正是由於 Android 程序把內存控制的權力交給了 Generational Heap Memory,一旦出現內存泄漏和溢出方面的問題,排查錯誤將會成爲一項異常艱難的工做。除此以外,部分 Android 應用開發人員在開發過程當中並無特別關注內存的合理使用,也沒有在內存方面作太多的優化,當應用程序同時運行愈來愈多的任務,加上愈來愈複雜的業務需求時,徹底依賴 Android 的內存管理機制就會致使一系列性能問題逐漸呈現,對應用的穩定性和性能帶來不可忽視的影響,所以,解決內存問題和合理優化內存是很是有必要的。

在開發的過程,若是方法不當的話,很容易形成內存泄漏,接下來,來講一下哪些情景容易出現內存泄漏。

內存泄漏出現的情景
  • 單例中引用的上下文Context,引用了Activity中的Context, 這樣會形成內存泄漏,要引用Application中的Context;
  • 資源性對象未關閉。好比Cursor、File文件等,每每都用了一些緩衝,在不使用時,應該及時關閉它們。
  • 註冊對象未註銷。好比事件註冊後未註銷,會致使觀察者列表中維持着對象的引用。
    類的靜態變量持有大數據對象。
  • 非靜態內部類的靜態實例。
  • Handler臨時性內存泄漏。若是Handler是非靜態的,容易致使 Activity 或 Service 不會被回收。
  • 容器中的對象沒清理形成的內存泄漏。
  • WebView。WebView 存在着內存泄漏的問題,在應用中只要使用一次 WebView,內存就不會被釋放掉。
內存優化的方案
  • 對象引用。強引用、軟引用、弱引用、虛引用四種引用類型,根據業務需求合理使用不一樣,選擇不一樣的引用類型。
  • 減小沒必要要的內存開銷。注意自動裝箱,增長內存複用,好比有效利用系統自帶的資源、視圖複用、對象池、Bitmap對象的複用。
  • 使用最優的數據類型。好比針對數據類容器結構,可使用ArrayMap數據結構,避免使用枚舉類型,使用緩存Lrucache等等。
  • 圖片內存優化。能夠設置位圖規格,根據採樣因子作壓縮,用一些圖片緩存方式對圖片進行管理等等。圖片的壓縮幾種方案;
內存分析工具

作內存優化前,須要瞭解當前應用的內存使用現狀,經過現狀去分析哪些數據類型有問題,各類類型的分佈狀況如何,以及在發現問題後如何發現是哪些具體對象致使的,這就須要相關工具來幫助咱們。如下介紹幾種內存分析工具

  • Memory Monitor
    Memory Monitor 是一款使用很是簡單的圖形化工具,能夠很好地監控系統或應用的內存使用狀況.
    主要有如下功能:

(1).顯示可用和已用內存,而且以時間爲維度實時反應內存分配和回收狀況。
(2).快速判斷應用程序的運行緩慢是否因爲過分的內存回收致使。
(3).快速判斷應用是否因爲內存不足致使程序崩潰。

  • Heap Viewer

Heap Viewer 的主要功能是查看不一樣數據類型在內存中的使用狀況,能夠看到當前進程中的 Heap Size 的狀況,分別有哪些類型的數據,以及各類類型數據佔比狀況。經過分析這些數據來找到大的內存對象,再進一步分析這些大對象,進而經過優化減小內存開銷,也能夠經過數據的變化發現內存泄漏。

主要有如下功能:
(1)實時查看App分配的內存大小和空閒內存大小
(2)發現Memory Leaks

Heap Viewer不光能夠用來檢測是否有內存泄漏,對於內存抖動,咱們也能夠用該工具檢測,由於內存抖動的時候,會頻繁發生GC,這個時候咱們只須要開啓Heap Viewer,觀察數據的變化,若是發生內存抖動,會觀察到數據在段時間內頻繁更新。

  • Allocation Tracker

Memory Monitor 和 Heap Viewer 均可以很直觀且實時地監控內存使用狀況,還能發現內存問題,但發現內存問題後不能再進一步找到緣由,或者發現一塊異常內存,但不能區別是否正常,同時在發現問題後,也不能定位到具體的類和方法。這時就須要使用另外一個內存分析工具 Allocation Tracker,進行更詳細的分析, Allocation Tracker 能夠分配跟蹤記錄應用程序的內存分配,並列出了它們的調用堆棧,能夠查看全部對象內存分配的週期。

  • Memory Analyzer Tool(MAT)

MAT 是一個快速,功能豐富的 Java Heap 分析工具,經過分析 Java 進程的內存快照 HPROF 分析,從衆多的對象中分析,快速計算出在內存中對象佔用的大小,查看哪些對象不能被垃圾收集器回收,並能夠經過視圖直觀地查看可能形成這種結果的對象。

穩定性優化

Android 應用的穩定性定義很寬泛,影響穩定性的緣由不少,好比內存使用不合理、代碼異常場景考慮不周全、代碼邏輯不合理等,都會對應用的穩定性形成影響。其中最多見的兩個場景是:Crash 和 ANR,這兩個錯誤將會使得程序沒法使用,比較經常使用的解決方式以下:

  • 提升代碼質量。好比開發期間的代碼審覈,看些代碼設計邏輯,業務合理性等。

  • 代碼靜態掃描工具。常見工具備Android Lint、Findbugs、Checkstyle、PMD等等。

  • Crash監控。把一些崩潰的信息,異常信息及時地記錄下來,以便後續分析解決。

  • Crash上傳機制。在Crash後,儘可能先保存日誌到本地,而後等下一次網絡正常時再上傳日誌信息。

做者:android的那點事 連接:https://www.jianshu.com/p/d71b51a0e29f 來源:簡書 簡書著做權歸做者全部,任何形式的轉載都請聯繫做者得到受權並註明出處。
相關文章
相關標籤/搜索