這是來自一位粉絲「MeloDev」的投稿,講真,我這裡投稿的不少,但是只有我自己覺得很不錯的才會通過,這篇文章我覺得對大家有用,而且性能優化也算是我面試必問的一個話題了,所以這裡推薦給大家。微信不支持連結,可點擊「閱讀原文」查看原文。
寫在前面
公司給了我一周的時間去學習Android性能的優化,參考了張明雲老師的一片文章,並且用公司的實際項目進行測試(附有截圖),還進行了一些知識點,注意事項以及很多網址連結的補充,希望這篇博文能讓做性能測試的朋友們少走一些彎路。
文中沒有貼出大段代碼,但是幾乎所有的知識點都有連結,點進去就能看你想看的。轉載註明出處。
性能指標
1. 布局複雜度:布局複雜會導致布局需要更長的時間,從而導致進入應用慢、頁面切換慢;
2. 耗電量:耗電量大會導致機器發熱、縮短機器的有效使用時長;
3. 內存:內存消耗大會導致頻繁GC,GC時會暫停其它工作,導致頁面卡頓;內存洩露會導致剩餘可用內存越來越小;內存不足會導致應用異常;
4. 網絡:頻繁的網絡訪問會導致耗電和影響應用的性能;網絡交互數據大小會影響網絡傳輸的效率;
5. 程序執行效率:糟糕的代碼會嚴重影響程序的運行效率,UI線程過多的任務會阻塞應用的正常運行,長時間持有某個對象會導致潛在的內存洩露,頻繁的IO操作、網絡操作而不用緩存會嚴重影響程序的運行效率。
一、布局複雜度的優化
關於布局的優化,主要分兩個大方向
1. 實現相同界面效果並且層級結構相同時,選用何種Layout最好
在Android中單獨的布局性能:
FrameLayout>LinearLayout>RelativeLayout
可供參考的網址:「LinearLayout與RelativeLayout的性能比較」
總結:
2. 減少布局的層級結構
「HierarchyViewer的使用」
「無線UIViewer下載」
測試圖片如下:
當前界面的UI布局層級如上圖所示
總結:
布局優化相關網址:
「三種優化標籤的使用情景和優勢—張業興 」
「布局優化標籤的源碼分析」
有關布局優化的一些基礎知識準備(郭霖老師的兩篇博客):
「Android LayoutInflater原理分析,帶你一步步深入了解View(一) 」
「Android視圖繪製流程完全解析,帶你一步步深入了解View(二)」
二、Android開發者模式—GPU過渡繪製
GPU過度繪製定義:
如果你粉刷過一個房間或一所房子,就會知道給牆壁塗上顏色需要做大量的工作。假如你還要重新粉刷一次的話,第二次粉刷的顏色會覆蓋住第一次的顏色,第一次的顏色就永遠不可見了,等於你第一次粉刷做的大量工作就完全被浪費掉。這太可怕了。
同樣的道理,如果在你的應用程式中浪費精力去繪製一些東西同樣會產生性能問題。過度繪製這個名詞就是用來描述屏幕上一個像素在單個幀中被重繪了多少次。
GPU過度繪製就指的是在屏幕一個像素上繪製多次(超過一次),GPU過度繪製或多或少對性能有些影響。
GPU過度繪製分析:
過度繪製其實是一個性能和設計的交叉點。我們在設計上追求很華麗的視覺效果,但一般來說這種視覺效果會採用非常多的層疊組件來實現,這時候就會帶來過度繪製的問題。我們再來看看具體顯示在Android界面層級關係:
當我們來繪製一個界面時,會有一個windows,然後是建立Activity,在Activity裡可以建立多個view,或view group,view也可以嵌套view。這些組件從上到下分布,上面的組件是可以被用戶看見的,而在下面的組件是不可見的,但是我們依然要花很多時間去繪製那些不可見的組件,因為在某些時候,它也可能會顯示出來。
檢測過度繪製:
設置-開發者選項-調試GPU過度繪製-顯示過度繪製區域(過度渲染等,不同機器可能不同)
測試的顏色標識含義:
項目測試截圖:
可以看到項目中並不存在太大問題,有關減少過度繪製的一些建議:
1. 太多重疊的背景
這個問題其實最容易解決,建議前期在設計時儘量保持整體背景統一,另外開發可以檢查你在布局和代碼中設置的背景,有些背景是被隱藏在底下的,它永遠不可能顯示出來,這種沒必要的背景一定要移除,因為它很可能會嚴重影響到app的性能。
2. 太多重疊的view
第一個建議是:使用ViewStub來加載一些不常用的布局,它是一個輕量級且默認不可見的視圖,可以動態的加載一個布局,只有你用到這個重疊著的view的時候才加載,推遲加載的時間。第二個建議是:如果使用了類似viewpager+Fragment這樣的組合或者有多個Fragment在一個界面上,需要控制Fragment的顯示和隱藏,儘量使用動態地Inflation view,它的性能要比SetVisiblity好。
3. 複雜的Layout層級
這裡的建議比較多一些,首先推薦用Android提供的布局工具Hierarchy
三、Android中耗電量的測試
「深入淺出Android App耗電量統計」
測試截圖:
本人認為這一點沒有過多補充的,大多數App都不會消耗過多的電量。
四、內存、CPU、GPU
應用運行時內存使用情況查看:Android Studio—Memory/CPU/GPU
通常這種測試應該使用一個自動化工具(monkey)去不停的點擊App,或者切換界面,來觀察內存、cpu的情況。
1. 內存
測試截圖:
在地圖界面不斷地刷新,正常的內存成鋸齒狀分布。
需要注意的情況:
出現了針狀分布,說明內存發生了突變,如果內存峰值不能降下來,就說明出現了內存溢出,就值得引起我們的關注了。
2. CPU
測試圖片:
3. 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. LeakCanary
LeakCanary是一個檢測內存洩露的開源類庫。你可以在 debug
包種輕鬆檢測內存洩露。強烈推薦LeakCanary,大多數公司都在使用它進行內存洩漏的測試。
以下是我找到的學習資料,寫的非常棒:
「LeakCanary: 讓內存洩露無所遁形」
「LeakCanary 中文使用說明」
具體使用請參考以上兩個連結,下面給出一個測試截圖,供大家直觀感受其便捷和強大的功能。
結論: LeakCanary非常直觀的展現了MainActivity出現了內存洩漏,並且指出引用路徑中的哪個引用是不該有的,然後修復問題。總而言之非常好用,處理內存洩漏首選的工具。
2. GT
GT是騰訊開發的一款APP的隨身調測平臺,利用GT,可以對CPU、內存、流量、點亮、幀率/流暢度進行測試,還可以查看開發日誌、crash日誌、抓取網絡數據包、APP內部參數調試、真機代碼耗時統計等等,需要說明的是,應用需要集成GT的sdk後,GT這個apk才能在應用運行時對各個性能進行檢測。
「GT官方網址」
下面是使用GT測試項目的截圖:
具體圖片是什麼含義,大家去點擊官網去了解學習就可以,GT還是很全面好用的,慢慢發掘吧。