編輯:Android資訊
無論你的應用多麼有創新性、有用,如果它卡得要命,或者非常消耗內存,那麼每人將會願意使用它。
因此,性能變得尤為重要。當你忙碌於構建精美的用戶界面或者完成新的特性時,你可能容易忘卻掉一些性能相關的事情。
這也是為什麼有Google Play的應用審核機制的原因之一。
這篇文章中,你會看到每個Android工程師需要了解的一些性能問題。你將會學會使用Android SDK提供的、已安裝在你的設備中的工具來測試這些問題是否發生在你自己的應用中。
如果在你的應用中發現了一個性能問題,你肯定會想修復它。我們還會看一看如何使用Android SDK 工具來獲取更多關於那些沒有覆蓋到的性能問題的相關信息。一旦你有了這些信息,你將會對如何提升應用性能有一個更深刻的理解,並且能夠構建出讓用戶喜愛的App。
你應用的用戶界面是連接用戶的紐帶,但是創建漂亮的界面只是挑戰的其中一面,你還需要確保用戶界面流暢的運行。
一個常見的問題就是用戶界面卡頓,出現這種情況的原因可能是overdraw。Overdraw是屏幕上的某個像素在同一幀的時間內被繪制了多次。
例如,想象一下一個有藍色的背景文本,Android不僅會繪制對用戶可見的藍色區域,而是會繪制整個藍色的背景以及上面的文本。這意味著一些像素會被兩次繪制,這就是過度繪制。
一些如上述例子所說的過度繪制示例是不可避免的。然而,過多的多度繪制會引發明顯的性能問題,因此你必須將過度繪制的可能性降到最小。
檢測應用中的過度繪制相對來說比較簡單。大量的過度繪制會引出其他用戶界面相關問題,例如視圖層級過於復雜等。基於這些原因,當你測試你的App的性能問題時,從過度繪制開始是一個明智的選擇。
好消息是你的Android設備上已經內置了檢測過度繪制的工具。
因此你需要做的第一步就是安裝你要測試的App到你的設備中。然後打開設置頁面,選擇開發選項(Developer Options)->調試GPU 過度繪制(Debug GPU Overdraw),然後選擇“顯示過度繪制區域(Show overdraw area)”。如下圖所示。
這個工具使用色塊來代表不同數量的過度繪制。剩下的事情就是啟動你要測試的應用,然後觀察它的過度繪制情況。
一旦你發現了某個區域有嚴重的過度繪制,最簡單的方法就是打開你應用的xml文件找到過度重疊的區域,特別是那些不可見的drawable對象和被繪制在其他控件上的背景,以此來降低這些地方的過度繪制。
你也應該查找那些背景屬性設置為白色,並且它的父視圖背景也設置為白色的區域。所有這些都會引起嚴重的過度繪制。
Android系統能自動的降低一些簡單的過度繪制,但是這些對於復雜的自定義View並沒有什麼價值,因為Android不會知道你如何繪制你的內容。
如果你在App中使用了復雜的自定義View,你可以為使用clipRect
函數為你的視圖定義可繪制區域的邊界。更新相關信息可以參考official Android documentation.
另一個常見的性能問題就是應用的視圖層級。為了渲染每個視圖,Android都會經歷這三個階段 :
花在這三個階段的時間與View層級中的View的數量成正比,這就意味著降低App渲染時間的最簡單的方法就是識別和移除那些並沒有什麼卵用的UI元素。
即使在你的視圖層級上的所有View都是必須的,不同的布局方式也可能對測量過程產生重要的影響。通常來說,你的視圖層級越深,花在測量視圖的時間就越長。
在視圖渲染期間,每個View都要向它的父View提供它自己的尺寸。如果父view發現了任意一個尺寸問題,那麼它會強制要求所有的子視圖重新測量。
即使沒有錯誤發生,重新測量也可能出現。例如,為了正確的進行布局RelativeLayout通常會對它們的子視圖進行兩次測量。子視圖使用了layout_weight
屬性的LinearLayout也會對它的子視圖進行兩次測量。
這些都取決於你的布局方式,測量和重新測量的代價非常昂貴,它會嚴重影響你的渲染速度。
確保你的用戶界面渲染流暢的關鍵就是移除任何非必須的View以及減少你的View層級。
Hierarchy Viewer是一個能夠將你完整的View層級可視化的工具,這個工具能夠幫助你發現冗余的View以及嵌套的布局。
在我們進一步了解Hierarchy Viewer之前,你需要知道它的一些規則。首先Hierarchy Viewer只能與正在運行的App進行交互,而不是你的源代碼。這就是說你需要將App安裝到你的設備或者模擬器上。
還有一個最重要的問題,就是默認情況下Hierarchy Viewer只能與運行開發版Android系統的設備進行交互(譯者注: 一般來說,使用模擬器即可)。如果你沒有開發設備,那你需要添加ViewServe
class到你的應用中。
了解這些之後就讓我們打開Android Studio,並且選擇”tools” -> “Android” -> “Android Device Monitor”,如圖所示。
然後點擊Hierarchy View按鈕,如下圖所示。
屏幕左邊的Windows標簽下列出了所有Android設備和模擬器。選擇你的設備後,你會看到你設備上運行的所有進程。選中你要檢測的進程,然後你會看到三個自動更新的視圖層級區域。
這三個窗口提供了視圖層級的三個不同可視化展示。
Hierarchy View中有三個窗口。如果你在一個窗口中選擇了一個View,那麼它會在另外兩個中高亮顯示。你能同時使用這三個窗口查找View層級中的冗余視圖。
如果你不確定一個View是否是UI界面中的必須元素,最簡單的方法就是到Tree View窗口點擊這個節點。你將會看到該View是如何顯示在屏幕的預覽,此時你就可以確切地知道該View是否是必須的。
但是即使一個View對最終的渲染效果有貢獻也並不意味著它不會引起嚴重的性能問題。你已經看到了如何通過Hierarchy Viewer來找到明顯的嵌套布局,但是如果這引起的性能問題並不那麼明顯呢?或者還有其他的原因使得該視圖渲染得非常慢?
好消息就是你還可以通過Hierarchy Viewer來剖析每個View在不同的渲染階段的耗時。當性能問題的原因不那麼明顯時,這是你發現問題的另一途徑。
下個章節我將為你展示如何通過Hierarchy Viewer來剖析每個View的渲染時間來找到潛伏在問題表面的性能問題。
定位你的用戶界面瓶頸的最簡單方法就是收集每個View分別完成測量、布局、繪制的時間。
你不僅可以通過Hierarchy Viewer收集這些信息,Hierarchy Viewer還可以通俗易懂地向你展示這些數據,因此你可以通過這種形式來找到性能問題。
Hierarchy Viewer默認並不會顯示渲染時間。你需要到Tree View窗口添加這個信息,然後選擇你想要測試的根節點。下一步,在Hierarchy Viewer上點擊由綠、紅、紫的三個圓形色塊組成的按鈕,如圖所示。
三個圓點色塊就會顯示在每個節點上,從左到右,這些圓點分別代表 :
每個圓點都有顏色 :
當收集了這些數據之後,你不僅知道哪些View需要優化,你還會確切地知道是在渲染的哪個階段導致的問題。
哪些黃色、紅色的地方就是你需要開始優化的地方,這些性能指標與該視圖層級下的其他剖析節點也有關系。換句話說,你肯定會有一些視圖渲染得比其他的慢。
在開始改良你的View相關的代碼之前,摸著你的良心問一句該View渲染得比其他視圖慢是否有一個合理的原因,如果答案是否定的,那麼就開始你的View優化之旅吧。
Android是一個自動管理內存的開發環境,不要讓這個句話蒙蔽了,因為內存洩漏依舊是可能發生的。這是因為垃圾回收器只會移除那些不可達的對象。如果它不是一個不可達的對象,那麼該對象就不會被釋放掉。
這些不可達的對象陰魂不散,聚集在你的堆內存中,占用App的內存控件。如果你繼續洩漏對象,那麼可用的內存空間將會越來越小,GC操作就會頻繁觸發。
有兩個原因表明這是一個壞消息。首先,GC操作通常不會明顯地影響你的App性能,但是當內存控件較小時大量的GC操作會使你的App變慢,此時UI就不會那麼流暢了。第二問題是移動設備的內存空間相對來說較小,因此內存洩漏會快速地升級為內存溢出,導致應用Crash。
內存洩漏難以被檢測出。可能只有當用戶開始抱怨你的應用時你才能發覺內存洩漏問題。幸運地是,Android SDK提供了一些有用的工具來讓你找到這些問題。(譯者注 : Square的開源庫LeakCanary是查找內存洩漏的優秀工具,強烈建議大家使用)。
Memory Monitor是一個能夠實時獲取應用內存使用情況的工具。需要注意的是這個工具只能作用於正在運行的應用,因此確保你的要測試的應用已經安裝到你的設備中,並且你的設備已經連接到你的電腦上。
Memory Monitor已經內置在Android Studio中,因此你可以點擊Android Studio的底部的”Memory”這個tab來切換到內存監視頁面。當你切換到該頁面的時候,Memory Monitor就開始記錄你的內存使用情況了。
如果Memory Monitor沒有開始記錄,那麼確保你的設備是已經被選中的狀態。
如果Memory Monitor提示No debuggable applications,那麼你可以打開Android Studio的”Tools”菜單,選擇”Android”,然後確保選中了Enable adb integration。這個功能還不是很穩定,所以有時候你需要手動切換它的狀態。你也可以斷開設備與電腦的連接,然後再重連,這樣可能就OK了。
一旦Memory Monitor檢測到正在運行的應用,它就會顯示這個應用的內存使用情況。已使用的內存會被表示為深藍色,未分配的內存則會變為淺藍色。
花一些時間與你的設備交互,並且關注你的內存使用情況。最終已分配的內存會增長,直到沒有內存可用。此時,系統就會釋放觸發GC釋放內存,當你看到已分配的內存明顯的下降時就代表GC操作被觸發了。
GC通常情況下會將無用的內存釋放掉,但是當你看到App在短時間內快速增長或者GC變得非常頻繁,此時你就需要倍加小心了,這就是發生內存洩漏的信號!
如果你通過Memory Monitor來追蹤一個可疑的內存洩漏問題,你可能會看到Android系統會為你的App增大可用內存,TODO : 。
最終,你可能會看到你的App消耗了非常多的內存以至於系統無法再給你的應用更多的可用內存。如果你看到這種場景,那麼說明你在內存使用上犯了很嚴重的錯誤。
另一個能夠幫助你收集更新關於內存洩漏信息和其他內存相關問題的工具是Android Device Monitor的DDMMS工具下的Heap。
Heap工具能夠通過顯示系統為你分配了多少內存來幫助你診斷內存洩漏問題。正如上面提到的,如果已分配的內存不斷地增長,那麼這是發生內存洩漏的明顯信號。
但是這個工具還提供了許多關於你的應用堆內存使用情況的數據,包含你的App內分配的各種對象、分配的對象數量以及這些對象占用了多少空間。這些額外的信息對於你追蹤內存洩漏極為有用。
你可以在Android Device Monitor工具中選擇DDMS,在Devices中選擇你要檢測的App。然後選擇Heap標簽,如圖所示。然後花一些時間與你的App進行交互以收集內存信息。
heap輸出信息會在GC事件之後,因為你可以手動點擊Cause GC來觸發GC,使得Heap內存數據盡快地顯示出來。
一旦GC事件被觸發了,heap標簽下就會更新App的堆內存使用信息,這些信息會在每次GC時更新。
在這篇文章中,我們學習了一些開發中最常見的性能問題,過度繪制、內存洩漏、緩慢的UI渲染。
相信你已經掌握了如何使用工具來檢查這些問題,以及如何獲取更新的信息來判斷你的應用中是否出現了這些性能問題。你有越多的信息,就越容易追蹤到問題的原因並且修復它。
Android SDK有很多工具可以供你診斷和定位性能問題。如果你想學習更多這方面的知識,你可以訪問u這兩篇官方文檔 Traceview and dmtracedump和 Allocation Tracker.
和前幾年iOS能夠憑籍App數量將安卓壓倒在地、安卓嬌喘吁吁起身不能的情況不同,現在安卓的App數量對比iOS平台可謂是有過之而無不及。2009年安卓系統起航伊始
模式的定義 適配器模式把一個類的接口變換成客戶端所期待的另一種接口,從而使原本因接口不匹配而無法在一起工作的兩個類能夠在一起工作。 使用場景 用電源接口做例子,筆
什麼是緩存? 緩存技術原理就是把用戶訪問的所有對象看作一個全集,經過算法標記哪些是用戶經常訪問的對象,把這些對象放到一個集合裡,這個集合是全集一個子集,下一次用戶
前言 無論你的應用多麼有創新性、有用,如果它卡得要命,或者非常消耗內存,那麼每人將會願意使用它。 因此,性能變得尤為重要。當你忙碌於構建精美的用戶界面或者完成新的