天天看點

Android應用優化Android應用優化

android應用優化主要從兩方面來考慮,其一是針對記憶體的優化,android裝置的記憶體相比較而言是比較珍貴,應及時回收不再使用的記憶體,防止記憶體洩露;其二是針對性能的優化,防止使用者使用是出現卡頓,響應慢或anr。

性能調優android官方有指導性的文檔,以及相關的調試工具,可參考android developer

另外這裡有一篇文章總結android應用性能調優方案的專題,寫得不錯。

本文主要介紹如何使用mat與hierarchy view工具來進行記憶體優化以及如何使用trace view進行性能調優。

在進行記憶體優化前,需要明确的幾個問題:

如何确認記憶體占用量

如何确認記憶體瓶頸或記憶體洩露

如何優化記憶體占用

如果順利解決了以上問題,則優化工作就取得比較理想的成果。

确認記憶體占用量有兩種方式,

通過dumpsys meminfo,可以查詢系統記憶體使用情況,包括各個程序的記憶體占用量

如:

通過android studio的android面闆中的memory監控資料,可以檢視所選程序的記憶體變化情況,如圖:

Android應用優化Android應用優化

記憶體是十分緊俏的資源,記憶體耗盡會導緻應用體驗差甚至出現oom,是以需要以最優的方式來使用記憶體。

記憶體洩露指的是記憶體中殘留一些對象,而這些對象在應用的後續流程中不再需要使用,但是由于被其它存活對象引用,是以其所占用的記憶體不能被回收,随着這種不可回收的無用對象的積累,記憶體會被慢慢吞噬,最終導緻outofmemory。

确定是否存在記憶體洩露的方法有兩種:

memory監控——粗略判斷

應用運作時,通過android studio的android-memory面闆可以監控記憶體的變化情況,如果反複在應用中執行操作會導緻記憶體持續上漲,則基本可以斷定存在記憶體洩露。

記憶體正常的應用在使用過程中,記憶體不會持續高漲,在進入某個頁面時,記憶體上漲,但是退出這個頁面時,記憶體會回落,是以會出現鋸齒狀的記憶體監控圖。

mat記憶體分析——精确分析記憶體洩露點

mat可以很友善的分析記憶體情況,用于定位記憶體洩露點經常事半功倍。

mat工具的使用(mat插件安裝請自行google)

memory leak suspects

該圖會列出幾個嫌疑最大的類,包括其執行個體的數量以及所占用記憶體大小,根據這些資訊,可以分析這些對象包含其他那些對象以及各自的大小是多少、從該對象出發,到gc root的路徑是什麼、該對象被那些對象引用或者引用了哪些對象、該對象所屬類引用了其他哪些類或别其他哪些類引用,具體含義見下表:

選項

含義

list objects-with outgoing references

以該對象為起點,向外的引用,指的是該對象引用的其他對象清單

list objects-with incoming references

以該對象為起點,向内的引用,指的是該對象被哪些對象引用

show objects by class-with outgoing references

以該對象所屬類為起點,向外的引用,指的是該對象所屬類引用了哪些類

show objects by class-with incoming references

以該對象所屬類為起點,向内的引用,指的是該對象所屬類類被哪些類引用

path to gc roots-with all references

從gc roots節點到該對象的引用路徑,包含所有引用類型

path to gc roots-exclude weak references

從gc roots節點到該對象的引用路徑,去除所有弱引用,其他類似

merge shortest paths to gc roots-with all references

從gc roots節點到該對象的最短引用路徑,包含所有引用類型

merge shortest paths to gc roots-exclude weak references

從gc roots節點到該對象的最短引用路徑,去除所有弱引用,其他類似

show retained set

列出該對象直接或間接占用的空間具體包含那些對象

oql(object query language)

select * from instanceof class

例如,查詢類com.yunos.tv.launchersdk.view.component.screencontainer的所有執行個體:

select * from instanceof com.yunos.tv.launchersdk.view.component.screencontainer

通過上述步驟确定哪個類的執行個體存在洩露或者哪個類占用的記憶體過多,則基本可以通過代碼來排查記憶體洩露或記憶體瓶頸的位置。

記憶體洩露的最常見的方式是:在view中定義了非static的内部類,并将該内部類注冊到了第三方接口中或注冊到單例中,當view destory時,由于外部持有該view的引用,導緻這個view不能被gc回收。

常見的洩露場景以及解決方案

context洩露

非static内部類洩露

public class mainactivity extends activity implements actionbar.tablistener {

}

Android應用優化Android應用優化

static leaky leak = null;

static class leaky {

記憶體瓶頸

這裡主要指cpu的性能優化,也就是application占用cpu時間的優化,app的cpu性能差主要展現在使用者操作時卡頓,比如進入應用時時間長,加載資料時導緻主線程阻塞,重新整理圖檔時阻塞主線程等。

主要從以下三個方面來介紹:

優化工具traceview介紹

如何确定性能瓶頸

如何優化

工欲善其事,必先利其器。選擇一個好的工具往往能做到事半功倍。traceview工具很強大,能快速定位出某個操作過程中,好時的操作在哪裡。

在android studio中,使用traceview的步驟如下:

打開android device monitor

連接配接adb

連接配接成功後,devices面闆會列出系統中所有的程序清單

Android應用優化Android應用優化

選中需要監測的程序

點選start method profiling

在應用中執行需要監測的操作

操作完成後,點選stop method profiling

會自動生成并打開.trace檔案,如圖所示:

Android應用優化Android應用優化

詳細使用方法可以參考[正确使用android性能分析工具——traceview

](http://bxbxbai.github.io/2014/10/25/use-trace-view/) 與 android性能調優工具traceview介紹

android monitor device打開traceview後,就可以分析應用在執行這個操作時,各個函數所花費的時間。如圖

Android應用優化Android應用優化

traceview分為上下兩個主要部分,上面部分列出了應用中運作的所有線程在這段時間内的圖形化運作情況,下面部分通過函數的樹狀調用,顯示了函數的執行時間。

下半部分的表格中,标題欄含義如下表:

序号

名稱

1

incl cpu time %

目前函數及其調用的子函數執行時所占cpu時間百分比

2

incl cpu time

目前函數及其調用的子函數一共執行時所占cpu時間

3

excl cpu time %

目前函數執行時所占cpu時間百分比(不包含調用子函數的執行時間)

4

excl cpu time

目前函數執行時所占cpu時間(不包含調用子函數的執行時間)

5

incl/excl real time %/na

對比1~4,real time指的是實際執行時間,不包括cpu上下文切換等

6

calls + recur calls / total

call表示這個方法調用的次數,recur call表示遞歸調用次數

7

cpu time / call

該函數平均執行時間

8

real time / call

該函數平均執行時間,不包括cpu上下文切換等

在了解上述名額後,可以比較直覺的看出各個函數執行時所占用的時間,而且能快速定位到時間最長的函數——也就是性能瓶頸。

一般可以抓住從三個方面切入:

從top_level來看,其children所占用的時間最長的top5

一類是調用次數不多,但每次調用卻需要花費很長時間的函數。可以通過cpu time / call的排序來排查,關注調用時間最長的前幾個方法的調用情況。

一類是那些自身占用時間不長,但調用卻非常頻繁的函數。可以通過calls + recur time / total排序,可以根據其調用鍊來追蹤調用量異常的原因。

找到性能瓶頸後,需要分析程式的執行流程,包括正常流程和異常流程。

可能的優化措施:

如果應用出現anr,将耗時的操作放到異步線程中去完成

如果資料處理過慢,考慮使用線程池

如果出現cpu占用持續高漲,且某些函數調用量很高,排查是否陷入死循環

繼續閱讀