對Android整個優化分析,非常棒,下面是自己的積累筆記??芍苯涌丛?。
界面檢測工具:
Fps: GPU檢測,
使用Lint進行資源及冗余UI布局等優化 (很強大,布局的冗余)
Memory檢測GC打印(發現問題),Allocation Tracker(定位問題 通過這個工具我們可以很方便的知道代碼分配了哪類對象、在哪個線程、哪個類、哪個文件的哪一行。) 進行UI卡頓分析。
常見應用開發中導致GC頻繁執行的原因主要可能是因為短時間內有大量頻繁的對象創建與釋放操作,也就是俗稱的內存抖動現象,或者短時間內已經存在大量內存暫用介于閾值邊緣,接著每當有新對象創建時都會導致超越閾值觸發GC操作。Traceview 應用程序中每個函數的執行時間
Systrace整個系統進行分析
使用traces.txt文件進行ANR分析優化.(發生Anr后adb pull /data/anr/traces.txt 輸出 )
代碼UI性能:
1.布局優化;盡量使用include、merge、ViewStub標簽,盡量使用GONE替換INVISIBLE,使用weight后盡量將width和heigh設置為0dp減少運算,Item存在非常復雜的嵌套時考慮使用自定義Item View來取代,減少measure與layout次數等。
2.列表及Adapter優化;盡量復用getView方法中的相關View,不重復獲取實例導致卡頓,列表盡量在滑動過程中不進行UI元素刷新等
3.背景和圖片等內存分配優化;盡量減少不必要的背景設置,圖片盡量壓縮處理顯示,盡量避免頻繁內存抖動等問題出現。
4.自定義View等繪圖與布局優化;盡量避免在draw、measure、layout中做過于耗時及耗內存操作,尤其是draw方法中,盡量減少draw、measure、layout等執行次數。
內存性能優化分析
系統級內存管理:
1. Linux在進程停止后就結束該進程,而Android把這些停止的進程都保留在內存中,直到系統需要更多內存時才選擇性的釋放一些,保留在內存中的進程默認(不包含后臺service與Thread等單獨UI線程的進程)不會影響整體系統的性能(速度與電量等)且當再次啟動這些保留在內存的進程時可以明顯提高啟動速度,不需要再去加載。
直白點就是說Android系統級內存管理機制其實類似于Java的垃圾回收機制
應用級內存管理:
1. 每個Android應用程序都執行在自己的虛擬機中,那了解Java的一定明白,每個虛擬機必定會有堆內存閾值限制(值得一提的是這個閾值一般都由廠商依據硬件配置及設備特性自己設定。
2. 運行的App在自己的虛擬機中內存管理基本就是遵循Java的內存管理機制了,系統在特定的情況下主動進行垃圾回收。但是要注意的一點就是在Android系統中執行垃圾回收(GC)操作時所有線程(包含UI線程)都必須暫停,等垃圾回收操作完成之后其他線程才能繼續運行。這些GC垃圾回收一般都會有明顯的log打印出回收類型,常見的如下:
LeakCanary:
dumpsys meminfo:
MAT Java堆內存泄露分析:
Android應用開發規避內存泄露建議
- Context使用不當造成內存泄露
- 非靜態內部類的靜態實例容易造成內存泄漏;即一個類中如果你不能夠控制它其中內部類的生命周期(譬如Activity中的一些特殊Handler等),則盡量使用靜態類和弱引用來處理
- 警惕線程未終止造成的內存泄露,譬如在Activity中關聯了一個生命周期超過Activity的Thread,在退出Activity時切記結束線程。(比如說AsyncTask等)
- 譬如在Activity中關聯了一個生命周期超過Activity的Thread,在退出Activity時切記結束線程
- 譬如在Activity中關聯了一個生命周期超過Activity的Thread,在退出Activity時切記結束線程
- 不要在執行頻率很高的方法或者循環中創建對象,可以使用HashTable等創建一組對象容器從容器中取那些對象,而不用每次new與釋放。
Android 內存溢出
(img)
產生原因:
1.應用代碼存在內存泄露,長時間積累無法釋放導致OOM;
2.應用的某些邏輯操作瘋狂的消耗掉大量內存(譬如加載一張不經過處理的超大超高清圖片等)導致超過閾值OOM。
Android應用規避內存溢出OOM建議
- 不要加載過大對象
- 優化界面交互過程中頻繁的內存使用;譬如在列表等操作中只加載可見區域的Bitmap、滑動時不加載、停止滑動后再開始加載。
- 有些地方避免使用強引用,替換為弱引用等操作。
- 避免各種內存泄露的存在導致OOM。
- 對批量加載等操作進行緩存設計,譬如列表圖片顯示,Adapter的convertView緩存等。
- 對于有緩存等存在的應用盡量實現onLowMemory()和onTrimMemory()方法。
- 對于有緩存等存在的應用盡量實現onLowMemory()和onTrimMemory()方法。
- 盡量管理好自己的Service、Thread等后臺的生命周期,不要浪費內存占用。
- 盡量在做一些大內存分配等可疑內存操作時進行try catch操作,避免不必要的應用閃退
- 盡量的優化自己的代碼,減少冗余,進行編譯打包等優化對齊處理,避免類加載時浪費內存。
HashMap, SparseArray,ArrayMap
HashMap:
HashMap內部使用一個默認容量為16的數組來存儲數據,數組中每一個元素存放一個鏈表的頭結點,其實整個HashMap內部結構就是一個哈希表的拉鏈結構。HashMap默認實現的擴容是以2倍增加,且獲取一個節點采用了遍歷法,所以相對來說無論從內存消耗還是節點查找上都是十分昂貴的。
SparseArray:
SparseArray比HashMap省內存是因為它避免了對Key進行自動裝箱(int轉Integer),它內部是用兩個數組來進行數據存儲的(一個存Key,一個存Value),它內部對數據采用了壓縮方式來表示稀疏數組數據,從而節約內存空間,而且其查找節點的實現采用了二分法,很明顯可以看見性能的提升。
ArrayMap:
ArrayMap內部使用兩個數組進行數據存儲,一個記錄Key的Hash值,一個記錄Value值,它和SparseArray類似,也會在查找時對Key采用二分法。
有了上面的基本了解我們可以得出結論供開發時參考,當數據量不大(千位級內)且Key為int類型時使用SparseArray替換HashMap效率高;當數據量不大(千位級內)且數據類型為Map類型時使用ArrayMap替換HashMap效率高;其他情況下HashMap效率相對高于二者。
Android應用ContentProviderOperation優化建議
ContentProvider是Android應用開發的核心組件之一,有時候在開發中需要使用ContentProvider對多行數據進行操作,我們的做法一般是多次調運相關操作方法,殊不知這種實現方式是非常低性能的,取而代之的做法應該是使用批量操作,具體為了使批量更新、插入、刪除數據操作更加方便官方提供了ContentProviderOperation工具類。所以在我們開發中遇到類似情景時請務必使用批量操作,具體的優勢如下:
? 所有的操作都在一個事務中執行,可以保證數據的完整性。
? 批量操作在一個事務中執行,所以只用打開、關閉一個事務。
? 減輕應用程序與ContentProvider間的多次頻繁交互,提升性能。
可以看見,這對于數據庫操作來說是一個非常有用的優化措施,煩請務必重視(我們項目優化過,的確有很大提升)。
Android應用移動設備電池耗電性能分析
adb shell dumpsys batterystats
常見耗電量最大原因基本都是因為網絡數據交互、GPS定位、大量內存性能問題、冗余的后臺線程和Service等造成。
Android應用耗電量優化建議
- 先進行網絡狀態判斷在執行。
- 對定位要求不太高的場景盡量使用網絡定位,而不是GPS定位
- 對于定時任務盡量使用AlarmManager,而不是sleep或者Timer進行管理。