編輯:關於Android編程
10.1 布局優化
10.1.1 Android UI渲染機制 10.1.2 避免Overdraw 10.1.3 優化布局層級 10.1.4 避免嵌套過多無用布局 10.1.5 Hierarchy Viewer 10.2 內存優化
10.2.1 什麼是內存 10.2.2 獲取Android系統內存信息 10.2.3 內存回收 10.2.4 內存優化實例 10.3 Lint工具 10.4 使用Android Studio的Memory Monitor工具 10.5 使用TraceView工具優化App性能
10.5.1 生成TraceView日志的兩種方法 10.5.2 打開TraceView日志 10.5.3 分析TraceView日志 10.6 使用MAT工具分析App內存狀態
10.6.1 生成HPROF文件 10.6.2 分析HPROF文件 10.7 使用Dumpsys命令分析系統狀態
無知識點
人眼所感覺的流暢畫面,需要畫面的幀數達到40幀每秒到60幀每秒,最佳fps大概在60fps左右 16ms也就是1000ms中顯示60幀畫面的單位時間,即1000/60,所以UI渲染時間間隔為16ms 如果不能在16ms內繪制完成,則會出現卡頓的效果 通過開發者選項,選擇”Profile GPU Rendering”並選中”On screen as bars”的選項,可以打開UI渲染時間的工具 每一條柱狀線包含三部分,藍色代表測量繪制Display List的時間,紅色代表OpenGL渲染Display List的時間,黃色代表CPU等待GPU處理的時間 中間的綠色橫線代表繪制間隔時間16ms,所以盡量保持在綠色之下
Overdraw,過度繪制會浪費很多的CPU、GPU資源 Android系統在開發者選項中提供了這樣一個檢測工具,”Enable GPU Overdraw” 通過這個工具可以查看當前區域中繪制次數,從而盡量優化繪圖層次,盡量增大藍色的區域,減少紅色的區域
Android中,系統對View進行測量、布局和繪制時,都是通過對View數的遍歷來進行操作的 如果View樹太高,就會嚴重影響測量、布局和繪制的速度,因此適當減少View樹的高度,Google建議View樹高度不宜超過10層 現在版本的Android,Google已經使用RelativeLayout來替代LinearLayout作為默認的根布局,,其原因就是降低LinearLayout嵌套所產生布局樹高度
使用< include>標簽重用Layout 使用< ViewStub>實現View的延遲加載< include>標簽重用,首先編寫common_ui.xml文件:
接著在主布局中引用:
這樣,common_ui就被引用了,其中include標簽裡面屬性會覆蓋common_ui裡面的屬性
使用< ViewStub>實現View的延遲加載,< ViewStub>是個輕量級的組件,它不僅不可視,而且大小為0,首先編寫not_often_use.xml文件
接著在主布局中引用:
這個時候是在布局中見不到這個ViewStub的布局的,有兩種方法可以來重新顯示這個View:
VISBLE
ViewStub mViewStub = (ViewStub) findViewById(R.id.not_often_use); mViewStub.setVisibility(View.VISIBLE);
inflate
ViewStub mViewStub = (ViewStub) findViewById(R.id.not_often_use); View inflateView = mViewStub.inflate();
這兩種方法唯一區別:
inflate()方法可以返回引用布局,從而可以通過View.findViewById()方法找到相對應控件< ViewStub>標簽與設置View.GONE有什麼區別:
它們的共同點就是在初始化時不會顯示,但是< ViewStub>標簽只會在顯示時,才會去渲染整個布局,而View.GONE在初始化布局樹的時候就已經添加在布局樹上了,相比之下,< ViewStub>標簽的布局具有更高的效率
通常情況下,Hierarchy Viewer無法在真機上使用,只能在模擬器上使用 Google大神提供了一個開源軟件View Server,讓普通手機也能使用Hierarchy Viewer,軟件網址http://github.com/romainguy/ViewServer Hierarchy Viewer位於sdk\tools目錄下,打開hierarchyviewer.bat啟動程序 關於Hierarchy Viewer的使用可查看下面的博客:Hierarchy Viewer
無知識點
由於Android的沙箱機制,每個應用所分配的內存大小是有限度的,內存太低就會觸發LMK:Low Memory Killer機制,我們所說的內存是指手機的RAM,它包括以下幾個部分:
寄存器(Registers)
速度最快的存儲場所,因為寄存器位於處理器內部,在程序中無法控制 棧(Stack)
存放基本類型的數據和對象的引用,但對像本身不存放在棧中,而是存放在堆中 堆(Heap)
堆內存用來存放由new創建的對象和數組,在堆中分配的內存,由Java虛擬機的自動垃圾回收(GC)來管理 靜態存儲區域(Static Field)
靜態存儲區域就是指在固定的位置存放應用程序運行時一直存在的數據,Java在內存中專門劃分了一個靜態存儲區域來管理一些特殊的數據變量如靜態的數據變量 常量池(Constant Pool)
JVM虛擬機必須為每個被裝載的類型維護一個常量池,常量池就是該類型所用到常量的一個有序集合,包括直接常量(基本類型,String)和對其他類型、字段和方法的符號引用這些概念中最容易搞錯的是堆和棧的區分:
棧:當定義一個變量時,棧會為該變量分配內存空間,當該變量作用域結束後,這部分內存控件會被用作新的空間進行分配 堆:使用new的方式創建一個變量,那麼就會在堆中為這個對象分配內存控件,即使該對象的作用域結束,這部分內存也不會立即被回收,而是等待系統的GC進行回收我們可以通過代碼分析Heap中的內存狀態:
ActivityManager manager = (ActivityManager) getSystemService(Context.ACTIVITY_SERVICE); int heapSize = manager.getLargeMemoryClass();
Process Stats:系統內存監視服務,通過”Setting-Developer-options-Process Stats”來開啟這個功能,也可以使用Dumpsys命令來獲取這些信息:
adb shell dumpsys procstats
Meminfo:內存監視工具,通過”Settings-Apps-Running”中打開這個界面,也可以使用Dumpsys命令來獲取這些信息:
adb shell dumpsys meminfo
Java對於C、C++這類語言最大的優勢就是不用手動管理系統資源,Java創建了垃圾收集器線程來自動進行資源的管理 Java的GC是系統自動進行的,但何時進行卻是開發者無法控制的,即使調用System.gc()方法,也只是建議系統進行GC,系統不一定會采取你的建議 盡管再強大的算法,也難免存在部分對象忘記回收的想象,這就是造成內存洩露的原因
Bitmap優化:Bitmap是造成內存占用過高或OOM的最大威脅
使用適當分辨率和大小的圖片 及時回收內存 使用圖片緩存 代碼優化:任何Java類占用大約500字節的內存空間,創建一個類的實例會消耗大概15字節的內存
對常量使用static修飾符 使用靜態方法,靜態方法會比普通方法提高15%左右的訪問速度 減少不必要的成員變量 ,這點在Android Lint工具上已經集成檢測了,如果一個變量可以定義為局部變量,則會建議你不要定義為成員變量 減少不必要的對象,使用基礎類型會比使用對象更加節省資源, 同時更應該避免頻繁創建短作用域的變量 盡量不要使枚舉、少使用迭代器 對Cursor、Receiver、Sensor、Fiie等對象,要非常注意對它們的創建,回收與注冊、解注冊 避免使用IOC框架,IOC通常使用注解、反射來進行實現,雖然現在Java對反射的效率已經進行了很好的優化,但大量使用反射依然會帶來性能的下降 使用RenderScript、OpenGL來進行非常復雜的繪圖操作 使用SurfaceView來替代View進行大量、頻繁的繪圖操作 盡量使用視圖緩存,而不是每次都執行inflaler()方法解析視圖
Android Lint工具是Android Studio中集成的一個Android代碼提示工具
Memory Monitor工具是Android Studio自帶的一個內存監視工具,通過Android Studio右下角”Memory Monitor”打開”Memory Monitor”工具
TraceView是一個Android下的可視化性能調查工具,用來分析TraceView日志
通過代碼生成精准范圍的TraceView日志:
通過調用Debug.startMethodTracing()方法開啟監聽,調用Debug.stopMethodTracing()方法結束監聽,通常會在onCreate時開啟監聽,在onDestroy時結束監聽 TraceView日志將會保存到”/sdcard/dmtrace.trace”目錄下,因此需要在權限中增加:
當然除了默認輸出日志名,還可以自定義路徑和日志名,最後通過ADB命令,將日志文件導出到本地:
adb pull /sdcard/trace_log.trace/local/LOG/
通過Android Device Monitor生成TraceView日志:
打開Android Device Monitor工具,選擇要調試的進程,點擊工具欄中的”start method profiling”按鈕,打開,再次點擊”start method profiling”按鈕即可結束 TraceView提供兩種監聽方式:
整體監聽:跟蹤每個方法執行的全部過程,這種方式資源消耗比較大 抽樣監聽:按照指定的頻率來進行抽樣調查,這種方式需要執行較長時間來獲取較精准的樣本數據
可以使用SDK中的”sdk\tools\traceview.bat”工具打開 可以在Android Device Monitor工具下,的File菜單選擇Open File打開
時間軸區域:顯示了不同線程在不同時間段內的執行情況
在時間軸中,每一行都代表了一個獨立的線程 使用鼠標滾輪可以放大時間軸 不同色塊代表不同的執行方法,色塊的長度,代表了方法所執行的時間 Profile區域:顯示你選擇的色塊所代表的方法在該色塊所處的時間段內的性能分析
Incl CPU Time:某方法占用CPU的時間 Excl CPU Time:某方法本身(不包含子方法)占用CPU的時間 Incl Real Time:某方法真正執行的時間 Excl Real Time:某方法本身(不包含子方法)真正執行的時間 Calls+RecurCalls:調用次數+遞歸回調的次數每個時間都包含兩列,一個是實際的時間,另一個是百分比,如果占用時間長且Calls+RecurCalls次數少,那麼就可以列為懷疑對象
MAT工具是一個分析內存的強力助手
打開Android Device Monitor工具,選擇要監聽的線程,並點擊菜單欄中的”Update Heap”按鈕
在Heap標簽中點擊”Cause GC”按鈕,就會顯示當前內存狀態
這裡有一 個判斷當前是否存在內存洩漏的小技巧:當我們不停地點擊”Cause GC”按鈕的時,如果”data object”一欄中的”Total size”有明顯變化,就代表可能存在內存洩漏<喎?/kf/ware/vc/" target="_blank" class="keylink">vcD4NCgk8cD7Jz8PmysfK1ravsum/tEhlYXDXtMyso6zPwsPmteO797LLtaXAuLXEJnJkcXVvO0R1bXAgSFBST0YgRmlsZSZyZHF1bzuwtMWlPC9wPg0KPC9ibG9ja3F1b3RlPg0KPHA+PGltZyBhbHQ9"" src="/uploadfile/Collfiles/20161015/20161015092832430.png" title="\" />
系統會生成一個.hprof文件,默認名為包名.hprof,不過還不能直接使用MAT工具查看,還需要進行格式轉換,在SDK目錄的platform-tools目錄下,使用hprof-conv工具幫助轉換,命令如下:
D:\sdk\platform-tools>hprof-conv F:\Heap\com.handsome.heap.hprof heap.hprof格式命令:”hprof-conv infile outfile”生成heap.hprof文件利用MAT工具就可以進行內存分析
10.6.2 分析HPROF文件
打開MAT工具,選擇”Open a Heap Dump”選項,進入分析:
Histogram
Histogram直方圖,用於顯示內存中每個對象的數量、大小和名稱 在選擇對象上單擊鼠標右鍵,在彈出的快捷菜單中選擇”List objects-with incoming references”選項查看具體的對象 Dominator Tree
Dominator Tree支配樹會將內存中的對象按照大小進行排序,並顯示對象之間的引用結構 對象已經按照”Retained Heap”進行排序了,即按照對象及其持有的引用的內存總和進行排序,通過分析內存占用大的對象找出內存消耗的原因10.7 使用Dumpsys命令分析系統狀態
Dumpsys命令的功能非常強大,可使用的參數配置也非常多,Dumpsys官方信息:https://source.android.com/devices/input/dumpsys.html 使用Dumpsys命令,只需要輸入”adb shell dumpsys+參數”即可
adb shell dumpsys activity:查看Activity棧的詳細信息 adb shell dumpsys meminfo:查看內存信息 adb shell dumpsys battery:查看電池信息 adb shell dumpsys package:查看包信息 adb shell dumpsys wifi:顯示Wi-Fi信息 adb shell dumpsys alarm:顯示alarm信息 adb shell dumpsys procstats:顯示內存信息
本文實例講述了Android Activity啟動模式之standard。分享給大家供大家參考,具體如下:Android的活動是通過任務Task來進行管理的,一個任務就是
行業背景: 今天,涉及通信產業鏈中的每個環節,都有Android的身影,Android是第一款完全
自定義PullToRefreshListView繼承ListView,在ListView頭部添加一個下拉的頭部布局。跟ListView用法完全一致。該自定義Listvie
之前跟大家介紹一個Alibaba的框架dexposed框架,此框架能夠動態的從線上完成一些補丁的工作。但是,由於它的性能和兼容性(不支持ART)所以,很多朋