1. 程式人生 > >Android的效能優化

Android的效能優化

Android的效能優化

寫在前面:

  公司給了我一週的時間去學習Android效能的優化,參考了張明雲老師的一片文章,並且用公司的實際專案進行測試(附有截圖),還進行了一些知識點,注意事項以及很多網址連結的補充,希望這篇博文能讓做效能測試的朋友們少走一些彎路。
  文中沒有貼出大段程式碼,但是幾乎所有的知識點都有連結,點進去就能看你想看的。轉載註明出處。

零:效能指標

  1. 佈局複雜度:佈局複雜會導致佈局需要更長的時間,從而導致進入應用慢、頁面切換慢;
  2. 耗電量:耗電量大會導致機器發熱、縮短機器的有效使用時長;
  3. 記憶體:記憶體消耗大會導致頻繁GC,GC時會暫停其它工作,導致頁面卡頓;記憶體洩露會導致剩餘可用記憶體越來越小;記憶體不足會導致應用異常;
  4. 網路:頻繁的網路訪問會導致耗電和影響應用的效能;網路互動資料大小會影響網路傳輸的效率;
  5. 程式執行效率:糟糕的程式碼會嚴重影響程式的執行效率,UI執行緒過多的任務會阻塞應用的正常執行,長時間持有某個物件會導致潛在的記憶體洩露,頻繁的IO操作、網路操作而不用快取會嚴重影響程式的執行效率。

    一:佈局複雜度的優化

    關於佈局的優化,主要分兩個大方向
    1. 實現相同介面效果並且層級結構相同時,選用何種Layout最好
    在Android中單獨的佈局效能:
FrameLayout>LinearLayout>RelativeLayout

可供參考的網址:LinearLayout與RelativeLayout的效能比較


總結:

  • RelativeLayout會讓子View呼叫2次onMeasure,LinearLayout 在有weight時,也會呼叫子View2次onMeasure;

  • RelativeLayout的子View如果高度和RelativeLayout不同,則會引發效率問題,當子View很複雜時,這個問題會更加嚴重。如果可以,儘量使用padding代替margin;

  • 在不影響層級深度的情況下,使用LinearLayout和FrameLayout而不是RelativeLayout;

  • 使用組合控制元件效能要好於兩個獨立控制元件,比如一個文字旁邊有一個圖片,這中情況最好要用DrawableLeft的這種屬性設定圖片;

2. 減少佈局的層級結構
  • HierarchyViewer---可檢視佈局層次結構,View繪製時耗時。
    HierarchyViewer的使用
  • 無線UIViewer---強烈推薦App工具,可在手機端直接實現HierarchyViewer的功能,檢視任意介面的UI佈局。
    無線UIViewer下載

測試圖片如下:


使用無線UIViewer測試出的結果


當前介面的UI佈局層級如上圖所示

總結:

  • 一些複用性很高的佈局檔案,比如一個App的標題欄,建議使用佈局重用include標籤,方便引入和共同管理。

  • 觀察上圖第三個層級和第四個層級,無論是Layout型別,還是所覆蓋的座標點,都是重合的,因為父FrameLayout作為一個Container,子FrameLayout作為一個子View的跟佈局,這種情況,可使用merge標籤進行佈局層級的優化。

  • 有些在特定情況下才會出現的介面,比如聯網之後,或者未必百分之百出現的介面,可用ViewStub標籤進行懶載入,效能明顯要優於加載出這個介面然後gone掉。

佈局優化相關網址:
三種優化標籤的使用情景和優勢---張業興
佈局優化標籤的原始碼分析

有關佈局優化的一些基礎知識準備(郭霖老師的兩篇部落格):
Android LayoutInflater原理分析,帶你一步步深入瞭解View(一)
Android檢視繪製流程完全解析,帶你一步步深入瞭解View(二)

二:Android開發者模式—GPU過渡繪製

GPU過度繪製定義:

如果你粉刷過一個房間或一所房子,就會知道給牆壁塗上顏色需要做大量的工作。假如你還要重新粉刷一次的話,第二次粉刷的顏色會覆蓋住第一次的顏色,第一次的顏色就永遠不可見了,等於你第一次粉刷做的大量工作就完全被浪費掉。這太可怕了。

同樣的道理,如果在你的應用程式中浪費精力去繪製一些東西同樣會產生效能問題。過度繪製這個名詞就是用來描述螢幕上一個畫素在單個幀中被重繪了多少次。

GPU過度繪製就指的是在螢幕一個畫素上繪製多次(超過一次),GPU過度繪製或多或少對效能有些影響。

GPU過度繪製分析:

過度繪製其實是一個性能和設計的交叉點。我們在設計上追求很華麗的視覺效果,但一般來說這種視覺效果會採用非常多的層疊元件來實現,這時候就會帶來過度繪製的問題。我們再來看看具體顯示在Android介面層級關係:

當我們來繪製一個介面時,會有一個windows,然後是建立Activity,在Activity裡可以建立多個view,或view group,view也可以巢狀view。這些元件從上到下分佈,上面的元件是可以被使用者看見的,而在下面的元件是不可見的,但是我們依然要花很多時間去繪製那些不可見的元件,因為在某些時候,它也可能會顯示出來。

檢測過度繪製:

設定-開發者選項-除錯GPU過度繪製-顯示過度繪製區域(過度渲染等,不同機器可能不同)


開啟過度繪製的流程圖

測試的顏色標識含義:


這裡寫圖片描述

專案測試截圖:


這裡寫圖片描述
這裡寫圖片描述
這裡寫圖片描述

可以看到專案中並不存在太大問題,有關減少過度繪製的一些建議:

  1. 太多重疊的背景
這個問題其實最容易解決,建議前期在設計時儘量保持整體背景統一,另外開發可以檢查你在佈局和程式碼中設定的背景,有些背景是被隱藏在底下的,它永遠不可能顯示出來,這種沒必要的背景一定要移除,因為它很可能會嚴重影響到app的效能。
  1. 太多重疊的view
第一個建議是:使用ViewStub來載入一些不常用的佈局,它是一個輕量級且預設不可見的檢視,可以動態的載入一個佈局,只有你用到這個重疊著的view的時候才載入,推遲載入的時間。第二個建議是:如果使用了類似viewpager+Fragment這樣的組合或者有多個Fragment在一個介面上,需要控制Fragment的顯示和隱藏,儘量使用動態地Inflation view,它的效能要比SetVisiblity好。
  1. 複雜的Layout層級

    這裡的建議比較多一些,首先推薦用Android提供的佈局工具Hierarchy

    三:Android中耗電量的測試

    深入淺出Android App耗電量統計

測試截圖:


這裡寫圖片描述

本人認為這一點沒有過多補充的,大多數App都不會消耗過多的電量。

四:記憶體、CPU、GPU

應用執行時記憶體使用情況檢視:Android Studio—Memory/CPU/GPU

通常這種測試應該使用一個自動化工具(monkey)去不停的點選App,或者切換介面,來觀察記憶體、cpu的情況。

  1. 記憶體

    測試截圖:


    這裡寫圖片描述

    在地圖介面不斷地重新整理,正常的記憶體成鋸齒狀分佈。

    需要注意的情況:


    這裡寫圖片描述

    出現了針狀分佈,說明記憶體發生了突變,如果記憶體峰值不能降下來,就說明出現了記憶體溢位,就值得引起我們的關注了。

  2. CPU

    測試圖片:


    這裡寫圖片描述
  1. GPU

    Android Studio 1.4增加一項新功能:分析GPU渲染功能。作者詳細講解這一新功能的分析方法。

    在GPU選項卡下,可以在螢幕上看到圖形化顯示的渲染每幀所花費的時間。圖形中每條都表示被渲染的一幀。顏色表示程序的不同週期:

    繪畫(藍色)
    表示View#onDraw()方法。那部分建立/更改DisplayList物件,然後轉換成GPU能夠理解的OpenGL命令。高的條形可能是檢視複雜,而要求更多的時間繪製它們的顯示列表,而許多檢視在短時間內就失效了。

    準備(紫色)
    在Lollipop中,加入另一個執行緒,以幫助UI執行緒渲染更快。這個執行緒叫:RenderThread。它的責任是轉換顯示列表為OpenGL命令,再發送給GPU。這樣在渲染過程中,UI執行緒可以開始處理下一個幀。這時UI執行緒將所有資源傳送給RenderThread。如果有許多資源要傳遞(如許多/繁重顯示列表),這一步可能需要較長時間。

    處理(紅色)
    執行顯示列表產生OpenGL命令。由於需要檢視重繪,如果有許多/複雜顯示列表要執行轉換,這一步可能需要較長時間。當檢視無效或是移動時,都要要重繪檢視。

    執行(黃色)
    傳送OpenGL命令到GPU。由於CPU傳送這些快取的命令到GPU,並期待收回乾淨快取,這就阻塞呼叫了。快取數量有限,並且GPU也很忙
    ——
    CPU會發現自己必須先等待快取釋放。因此,如果在這一步我們見高的條形,就可能意味著GPU在繪製UI時非常忙,這個繪製在短時間內太複雜了。

    測試截圖:


    這裡寫圖片描述

結論:

可以通過切換介面,看圖形的峰值和顏色去判斷繪製View每個階段所花費的時間,然後根據你的需求進行優化。

五:程式的執行效率

  1. 靜態程式碼檢查工具:Android studio—Analyze—Inspect Code…/Code cleanup… ,用於檢測程式碼中潛在的問題、存在效率問題的程式碼段並提供改善方案;

  2. DDMS—TraceView,用於查詢程式執行時具體耗時在哪;

  3. StrictMode:用於查詢程式執行時具體耗時在哪,需要整合到程式碼中;

六:知名的三方效能優化工具

  1. LeakCanary
    LeakCanary是一個檢測記憶體洩露的開源類庫。你可以在 debug
    包種輕鬆檢測記憶體洩露。強烈推薦LeakCanary,大多數公司都在使用它進行記憶體洩漏的測試。

    以下是我找到的學習資料,寫的非常棒:

    LeakCanary:
    讓記憶體洩露無所遁形

    LeakCanary
    中文使用說明

    具體使用請參考以上兩個連結,下面給出一個測試截圖,供大家直觀感受其便捷和強大的功能。


    這裡寫圖片描述
    這裡寫圖片描述

    結論: LeakCanary非常直觀的展現了MainActivity出現了記憶體洩漏,並且指出引用路徑中的哪個引用是不該有的,然後修復問題。總而言之非常好用,處理記憶體洩漏首選的工具。

  2. GT GT是騰訊開發的一款APP的隨身調測平臺,利用GT,可以對CPU、記憶體、流量、點亮、幀率/流暢度進行測試,還可以檢視開發日誌、crash日誌、抓取網路資料包、APP內部引數除錯、真機程式碼耗時統計等等,需要說明的是,應用需要整合GT的sdk後,GT這個apk才能在應用執行時對各個效能進行檢測。

    GT官方網址

    下面是使用GT測試專案的截圖:


    這裡寫圖片描述
    這裡寫圖片描述
    這裡寫圖片描述
    這裡寫圖片描述
    這裡寫圖片描述

    具體圖片是什麼含義,大家去點選官網去了解學習就可以,GT還是很全面好用的,慢慢發掘吧。



作者:MeloDev
連結:http://www.jianshu.com/p/be05874965d4
來源:簡書
著作權歸作者所有。商業轉載請聯絡作者獲得授權,非商業轉載請註明出處。