Android的性能優化
寫在前面:
公司給了我一周的時間去學習Android性能的優化,參考了張明云的一片文章,并且用公司的實際項目進行測試(附有截圖),還進行了一些知識點,注意事項以及很多網址鏈接的補充,希望這篇博文能讓做性能測試的朋友們少走一些彎路。
文中沒有貼出大段代碼,但是幾乎所有的知識點都有鏈接,點進去就能看你想看的。轉載注明出處。
零:性能指標
- 布局復雜度:布局復雜會導致布局需要更長的時間,從而導致進入應用慢、頁面切換慢;
- 耗電量:耗電量大會導致機器發熱、縮短機器的有效使用時長;
- 內存:內存消耗大會導致頻繁GC,GC時會暫停其它工作,導致頁面卡頓;內存泄露會導致剩余可用內存越來越??;內存不足會導致應用異常;
- 網絡:頻繁的網絡訪問會導致耗電和影響應用的性能;網絡交互數據大小會影響網絡傳輸的效率;
- 程序執行效率:糟糕的代碼會嚴重影響程序的運行效率,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下載
測試圖片如下:
當前界面的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過度繪制-顯示過度繪制區域(過度渲染等,不同機器可能不同)
測試的顏色標識含義:
項目測試截圖:
可以看到項目中并不存在太大問題,有關減少過度繪制的一些建議:
- 太多重疊的背景
這個問題其實最容易解決,建議前期在設計時盡量保持整體背景統一,另外開發可以檢查你在布局和代碼中設置的背景,有些背景是被隱藏在底下的,它永遠不可能顯示出來,這種沒必要的背景一定要移除,因為它很可能會嚴重影響到app的性能。
- 太多重疊的view
第一個建議是:使用ViewStub來加載一些不常用的布局,它是一個輕量級且默認不可見的視圖,可以動態的加載一個布局,只有你用到這個重疊著的view的時候才加載,推遲加載的時間。第二個建議是:如果使用了類似viewpager+Fragment這樣的組合或者有多個Fragment在一個界面上,需要控制Fragment的顯示和隱藏,盡量使用動態地Inflation view,它的性能要比SetVisiblity好。
-
復雜的Layout層級
這里的建議比較多一些,首先推薦用Android提供的布局工具Hierarchy
三:Android中耗電量的測試
--
深入淺出Android App耗電量統計
測試截圖:
本人認為這一點沒有過多補充的,大多數App都不會消耗過多的電量。
四:內存、CPU、GPU
應用運行時內存使用情況查看:Android Studio—Memory/CPU/GPU
通常這種測試應該使用一個自動化工具(monkey)去不停的點擊App,或者切換界面,來觀察內存、cpu的情況。
-
內存
測試截圖:
這里寫圖片描述在地圖界面不斷地刷新,正常的內存成鋸齒狀分布。
需要注意的情況:
這里寫圖片描述出現了針狀分布,說明內存發生了突變,如果內存峰值不能降下來,就說明出現了內存溢出,就值得引起我們的關注了。
-
CPU
測試圖片:
這里寫圖片描述
-
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每個階段所花費的時間,然后根據你的需求進行優化。
五:程序的執行效率
靜態代碼檢查工具:Android studio—Analyze—Inspect Code…/Code cleanup… ,用于檢測代碼中潛在的問題、存在效率問題的代碼段并提供改善方案;
DDMS—TraceView,用于查找程序運行時具體耗時在哪;
StrictMode:用于查找程序運行時具體耗時在哪,需要集成到代碼中;
六:知名的三方性能優化工具
-
LeakCanary
LeakCanary是一個檢測內存泄露的開源類庫。你可以在 debug
包種輕松檢測內存泄露。強烈推薦LeakCanary,大多數公司都在使用它進行內存泄漏的測試。以下是我找到的學習資料,寫的非常棒:
具體使用請參考以上兩個鏈接,下面給出一個測試截圖,供大家直觀感受其便捷和強大的功能。
這里寫圖片描述這里寫圖片描述結論: LeakCanary非常直觀的展現了MainActivity出現了內存泄漏,并且指出引用路徑中的哪個引用是不該有的,然后修復問題??偠灾浅:糜?,處理內存泄漏首選的工具。
-
GT GT是騰訊開發的一款APP的隨身調測平臺,利用GT,可以對CPU、內存、流量、點亮、幀率/流暢度進行測試,還可以查看開發日志、crash日志、抓取網絡數據包、APP內部參數調試、真機代碼耗時統計等等,需要說明的是,應用需要集成GT的sdk后,GT這個apk才能在應用運行時對各個性能進行檢測。
下面是使用GT測試項目的截圖:
這里寫圖片描述這里寫圖片描述這里寫圖片描述這里寫圖片描述這里寫圖片描述具體圖片是什么含義,大家去點擊官網去了解學習就可以,GT還是很全面好用的,慢慢發掘吧。