編輯:關於Android編程
本篇文章主要學習UI性能優化。
用戶感覺到卡頓的原理就是在渲染時出現了掉幀。Android系統要求 1s內渲染60幀,即渲染1幀必須要在16ms完成。如果你的界面沒有在16ms內准備好一幀,所以就不會進行渲染,屏幕也就不會刷新。結果就是用戶就是盯著一幀看了32ms,而不是16ms,因為刷新頻率的不一致,就使用戶感知到了卡頓。
官方出的性能優化視頻Android Performance Patterns: Why 60fps? 解釋說:
While 60 frames per second is actually the sweet pot. Great, smooth motion without all the tricks. And most humans can’t perceive the benefits of going higher than this number.
60fps是最恰當的幀率,是用戶能感知到的最流暢的幀率,而且人眼和大腦之間的協作無法感知到超過 60fps的畫面更新。
Now, it’s worth noting that the human eye is very discerning when it comes to inconsistencies in these frame rates
但值得注意的是人眼卻能夠感受到刷新頻率不一致帶來的卡頓現象,比如一會60fps,一會30fps,這是能夠被感受到的,即卡頓。
As an app developer, your goal is clear. Keep your app at 60 frames per second. that’s means you have got 16 milliseconds per frame to do all of your work.That is input, computing, network and rendering every frame to stay fluid for your users.
所以作為開發者,你必須要保證你的所有操作在16ms內完成包括輸入、計算、網絡、渲染等這些操作,才能保證應用使用過程的流暢性。
在知道了卡頓是因為掉幀後,我們就來探討引起掉幀的原因有哪些。
Process.THREAD_PRIORITY_BACKGROUND導致後台線程搶占UI線程cpu時間片,阻塞渲染操作; ANR;
接下來就針對這些原因使用性能分析工具進行分析,並提出可能有效的解決方法。
3. 開啟StrictMode
這是最簡單的檢測性能的方法,在Application中或者在開發者模式中開啟即可。
4. 減少布局復雜度
減少布局復雜度,可以從兩個方面著手:一是優化相同層級結構時,二是多層級布局結構時盡量減少層級。
4.1 在相同層級結構相同並且界面效果相同時,選擇性能高的ViewGroup
FrameLayout>LinearLayout>RelativeLayout,同時也可以自定義ViewGroup來減少計算量。
4.2 減少布局層次
the performance might improve by flattening the layout—make the layout shallow and wide, rather than narrow and deep.
扁平的布局可能比深層次的布局效率要高。這裡可以通過HierarchyViewer.profileNode進行數據觀察,並檢測布局冗余。
The Hierarchy Viewer application allows you to debug and optimize your user interface. It provides a visual representation of the layout’s View hierarchy (the View Hierarchy window) with performance information for each node in the layout, and a magnified view of the display (the Pixel Perfect window) to closely examine the pixels in your layout.
使用Hierarchy Viewer可以調試和優化應用的UI界面。並提供了可視化的View層級垂直視圖可以查看每個View節點的詳細信息,並且可以在像素級別上檢測你的布局。
4.3 減少布局復雜度可行的方法:
使用merge標簽
merge標簽就是為減少布局層次而生的,它通過減少View樹的層級來優化布局,而且可以減少過渡渲染,merge只能作為xml布局的根標簽使用。
如果在代碼中Inflate帶merge標簽的布局時,必須為這個自定義View指定一個父ViewGroup,並且設置attachToRoot為true。
使用ViewStub標簽,
ViewStub是一個用於在運行時加載布局資源、不可見、寬高為0的View,在布局文件中使用它只是用於占位,在代碼中沒有手動加載它時,並不會影響頁面的測量、繪制、顯示效率,在代碼中通過inflate加載ViewStub時,ViewStub會用在布局文件中為其指定的布局文件來代替它自身。ViewStub只能夠被inflate一次,一旦加載後ViewStub對象就會被置為空,需要判空。ViewStub標簽有對應的java類ViewStub.java。
5. 避免過渡繪制
通過開發者模式的 調試GPU過渡來開啟GPU過度渲染,Visualize GPU Overdraw。
GPU過度繪制指的是在屏幕一個像素上繪制多次(超過一次)。
過渡繪制用於檢測你的程序是否存在不必要的繪制,可以幫助開發者找出應用中過渡渲染的地方,減少不必要的過渡渲染以提高程序運行效率。
顏色
含義
無色
沒被渲染的區域、WebView等的渲染區域
藍色
1x過度繪制
綠色
2x過度繪制
淡紅色
3x過度繪制
紅色
4x(+)過度繪制
<喎?/kf/ware/vc/" target="_blank" class="keylink">vcD4NCjxwPjxjb2RlPjxjb2RlPtOm08PO3reozerIq9f2tb3Du9PQuf22ybvm1sajrNPFu6/Kx76hwb+x3MPisrux2NKqtcS5/bbJu+bWxqOszaizo8fpv/bPwrGj1qTNrNK7x/jT8rn9tsm75tbGydnT2sj9tM62vMrHus/A7bXEo6y8tNa70qrKx7P2z9a67Mmro6i1rbrsyau6zcnuuuzJq6OptcS12Le9o6y+zcrH0OjSqtPFu6+1xLXYt72hozwvY29kZT48L2NvZGU+PC9wPg0KPGJsb2NrcXVvdGU+DQoJPHA+PGNvZGU+PGNvZGU+udm3vc7EtbWjujxiciAvPg0KCTxhIGhyZWY9"https://developer.android.com/studio/profile/dev-options-overdraw.html">Debug GPU Overdraw Walkthrough
減少過渡繪制可行的方法:
去掉不必要的背景
每個Activity都會在AndroidManifest.xml中設置主題,主題的目的是設置界面的顯示風格,但在設置主題的時候通常情況下默認給Window設置了背景。Android系統在刷新整個界面時不僅僅是刷新Activity,還會刷新Window。
如果默認沒有去掉window的背景,並且在布局文件中給Activity設置了背景,就會存在過渡繪制的問題。
使用Space標簽
Space標簽可以只在布局文件中占位,不繪制,Space標簽有對應的java類Space.java。
Space類的draw()方法為空,即並不繪制本身,所以只做占位用,其顏色為transparent。
自定義控件時canvas.clipRect可以解決只刷新固定區域的問題,可參考DrawerLayout。
不必要的alpha值設置可以解決同一視圖被多次繪制的問題;
6. 使用GPU呈現模式圖
在開發者模式中開啟Profile GPU Rendering查看。在機器上看到GPU繪制圖形信息,分別展示了StatusBar、NavgationBar、Activity區域等的GPU渲染時間信息,隨著界面的刷新,界面上會以實時柱狀圖來顯示每幀的渲染時間,柱狀圖越高表示渲染時間越長,每個柱狀圖偏上都有一根代表16ms基准的綠色橫線,只要我們每一幀的總時間低於基准線就不會發生UI卡頓問題。
通過該工具若有柱狀圖超過基准線,便說明有丟幀,此時可以結合traceview和systrace來定位問題。
6、7、8這三塊都是解決掉幀問題,通過相關工具確認到具體代碼位置,然後進行優化。
官方文檔:
Profile GPU Rendering Walkthrough
Analyzing with Profile GPU Rendering
7. 使用systrace:
自己在mac上運行
systrace.py時需要安裝pyserial,我是通過
anaconda安裝。也可以直接通過DDMS使用systrace。
也可以通過命令行執行如下:
$ cd android-sdk/platform-tools/systrace
$ python systrace.py --time=10 -o mynewtrace.html sched gfx view wm
10秒後生成的html文件通過chrome打開,使用 WASD和M鍵 來查看,基本可以完全看到所渲染每一幀所消耗的時間,並且在圖表上提示了alert,點擊便可查看它所提示的信息,進而確認問題,提升性能。
8. 使用TraceView
TraceView 是 Android 平台特有的數據采集和分析工具,它主要用於分析 Android 中應用程序的 hotspot。TraceView 本身只是一個數據分析工具,而數據的采集則需要使用 Android SDK 中的 Debug 類或者利用 DDMS 工具。
可以通過DDMS進行數據采集,完成後會自動打開TraceView界面,便可進行分析。 使用代碼Debug.startMethodTracing(),Debug.stopMethodTracing() 來生成.trace文件,pull到電腦上後再打開該文件。這種使用可一般放在Application類中onCreate()方法內以進行冷啟動優化。
一般使用TraceView來分析兩類問題:
一類是調用次數不多,但每次調用卻需要花費很長時間的函數。 一類是那些自身占用時間不長,但調用卻非常頻繁的函數。
關於第一種,通常做法是先按Cpu Time/Call降序排序,然後看Incl Cpu Time的大小,綜合起來越大的性能問題越嚴重。
關於第二種,通常做法是按Calls + Recur Calls/Total降序排序,然後看Incl Cpu Time的大小,綜合起來越大的性能問題越嚴重
參數
參數解釋
Incl Cpu Time
方法自身及該方法調用的所有子方法所占時間和
Excl Cpu Time
方法自身所占時間,但不含內部調用其它函數所占用的CPU時間
Incl Real Time
某函數運行的真實時間(以毫秒為單位),內含調用其它函數所占用的真實時間
Excl Real Time
某函數運行的真實時間(以毫秒為單位),不含調用其它函數所占用的真實時間
Call+Recur Calls/Total
某函數被調用次數以及遞歸調用占總調用次數的百分比
Cpu Time/Call
某函數調用CPU時間與調用次數的比。相當於該函數平均執行時間
Real Time/Call
同CPU Time/Call類似,只不過統計單位換成了真實時間
相關文章:
TraceView性能優化工具使用
Android 編程下的 TraceView 簡介及其案例實戰
Android 常用的性能分析工具詳解:GPU呈現模式, TraceView, Systrace, HirearchyViewer
Android系統性能調優工具介紹
9. Use Lint
Android Lint is a static code scanning tool that helps you optimize the layouts and layout hierarchies of your applications, as well as detect other common coding problems.
Lint 是一個靜態的代碼掃描工具,可以幫助優化布局、布局層級和其他的一些問題。
Lint automatically runs whenever you compile your program. With Android Studio, you can also run lint inspections for a specific build variant, or for all build variants.
在Android Studio中可以在打開 Analyze > Inspect Code來檢測問題。
結語:
本篇文章大概介紹了用於UI性能問題分析的工具,並沒有列舉其使用場景和怎麼分析。關於工具,熟練使用還有待時日。另外,可以看看這篇文章 App優化之消除卡頓,這篇文章有大量的使用場景,而且通俗易懂。
1、前言webView是android中用於展示簡單的網頁或者加載一些html格式的很好的選擇,它提供了很多的操作上的封裝但同時又不失去靈活性,因為他提供了webView
最近在寫一個小項目,其中有一點用到了顯示EditText中輸入了多少個字符,像微博中顯示剩余多少字符的功能。在EditText提供了一個方法addTextChangedL
在計算機科學領域,反射是指一類應用,它們能夠自描述和自控制。也就是說,這類應用通過采用某種機制來實現對自己行為的描述(self-representation)和監測(ex
盡管Android正在被不斷開發,但Android 6.0是完全不同的,對於Android 6.0的幾個主要的變化,查看查看官網的這篇文章:http://develope