一、關(guān)于App性能優(yōu)化
1. 性能優(yōu)化分類
Google官方給出的性能優(yōu)化教程,主要分為以下幾類:
1)布局與UI渲染優(yōu)化
2)運算與內(nèi)存管理優(yōu)化
3)電池電量優(yōu)化
4)高效代碼相關(guān)Tips
5)多線程操作
官方鏈接:https://developer.android.com/training/best-performance.html
中文博客:https://aeli.gitbooks.io/android-training-course/content/best-performance.html
2. 渲染性能與UI卡頓
大多數(shù)用戶感知到的卡頓等性能問題的最主要根源都是因為渲染性能,Android系統(tǒng)很有可能無法及時完成那些復(fù)雜的界面渲染操作,Android系統(tǒng)每隔16ms發(fā)出VSYNC信號,觸發(fā)對UI進行渲染,如果每次渲染都成功,這樣就能夠達(dá)到流暢的畫面所需要的60fps,為了能夠?qū)崿F(xiàn)60fps,這意味著程序的大多數(shù)操作都必須在16ms內(nèi)完成。

如果你的某個操作花費時間是24ms,系統(tǒng)在得到VSYNC信號的時候就無法進行正常渲染,這樣就發(fā)生了丟幀現(xiàn)象。那么用戶在32ms內(nèi)看到的會是同一幀畫面。

用戶容易在UI執(zhí)行動畫或者滑動ListView的時候感知到卡頓不流暢,是因為這里的操作相對復(fù)雜,容易發(fā)生丟幀的現(xiàn)象,從而感覺卡頓。有很多原因可以導(dǎo)致丟幀,也許是因為你的layout太過復(fù)雜,無法在16ms內(nèi)完成渲染,有可能是因為你的UI上有層疊太多的繪制單元,還有可能是因為動畫執(zhí)行的次數(shù)過多。這些都會導(dǎo)致CPU或者GPU負(fù)載過重。
二、工具篇
我們可以通過一些工具來定位問題,比如可以使用HierarchyViewer來查找Activity中的布局是否過于復(fù)雜,也可以使用手機設(shè)置里面的開發(fā)者選項,打開Show GPU Overdraw等選項進行觀察。你還可以使用TraceView來觀察CPU的執(zhí)行情況,更加快捷的找到性能瓶頸。
1. HierarchyViewer
HierarchyViewer是我們優(yōu)化程序的工具之一,它是Android自帶的非常有用的工具,可以幫助我們更好地檢測和設(shè)計用戶界面,能夠以可視化的角度直觀地獲得UI布局設(shè)計結(jié)構(gòu)和各種屬性的信息,幫助我們優(yōu)化布局設(shè)計。但是獨立的HierarchyViewer已廢棄,Android Studio中建議使用Android Device Monitor。
需使用模擬器或開發(fā)版的真機,因為需要系統(tǒng)中的Hierarchy Viewer服務(wù)開啟。
使用方式:
1)點擊Tools->Android->Android Device Monitor,進入Android Device Monitor,切換到HierarchyViewer標(biāo)簽。

2)或者直接進入獨立的HierarchyViewer:進入sdk/tools路徑,找到HierarchyViewer,雙擊運行。

3)在左側(cè)樹狀結(jié)構(gòu)中選中要查看的activity,加載完畢后會顯示當(dāng)前界面的樹狀結(jié)構(gòu)層次,從PhoneWindow.DecorView出發(fā),右側(cè)是xml內(nèi)定義的布局結(jié)構(gòu),大小可以縮放,可以拖動,右側(cè)是屬性預(yù)覽區(qū)域。

4)觀察單個view,選擇單個view后會出現(xiàn)如下所示圖形,可以看到Measure、Layout、Draw的耗時,從左到右三個圓點,分別表示對Measure、Layout、Draw耗時性能的評級,按照性能從高到低,分別為綠色、黃色和紅色,浮窗上是具體的數(shù)值

通過使用HierarchyViewer,我們可以通過減少頁面層級,優(yōu)化布局結(jié)構(gòu)來實現(xiàn)UI性能的優(yōu)化,針對每個單獨控件的渲染性能數(shù)據(jù),可以獨立的針對某控件做特殊優(yōu)化。
2. GPU過度繪制
過度繪制就是Overdraw,是指在一幀的時間內(nèi)(16.67ms)像素被繪制了多次,理論上一個像素每次只繪制一次是最優(yōu)的,但是由于重疊的布局導(dǎo)致一些像素會被多次繪制,而每次繪制都會對應(yīng)到CPU的一組繪圖命令和GPU的一些操作,產(chǎn)生額外開銷,當(dāng)這個操作耗時超過16.67ms時,就會出現(xiàn)掉幀現(xiàn)象,也就是我們所說的卡頓,所以應(yīng)盡量減少Overdraw的發(fā)生。
Android提供了測量Overdraw的選項,在開發(fā)者選項-調(diào)試GPU過度繪制(Show GPU Overdraw),打開選項就可以看到當(dāng)前頁面Overdraw的狀態(tài),就可以觀察屏幕的繪制狀態(tài)。該工具會使用三種不同的顏色繪制屏幕,來指示overdraw發(fā)生在哪里以及程度如何,其中:
無顏色:沒有overdraw。像素只畫了一次。
藍(lán)色:overdraw 1倍。像素繪制了兩次。大片的藍(lán)色還是可以接受的(若整個窗口是藍(lán)色的,可以擺脫一層)。
綠色:overdraw 2倍。像素繪制了三次。中等大小的綠色區(qū)域是可以接受的但你應(yīng)該嘗試優(yōu)化、減少它們。
淺紅:overdraw 3倍。像素繪制了四次,小范圍可以接受。
暗紅:overdraw 4倍。像素繪制了五次或者更多。這是錯誤的,要修復(fù)它們。

減少過度繪制Tips:
- 不同控件容器特點不同,根據(jù)不同場景合理選擇控件容器,例如RelativeLayout
相對于LinearLayout,在某些場景下可減少嵌套層次,但LinearLayout使用簡單,效率也更高 - 去掉window的默認(rèn)背景,DecorView會創(chuàng)建默認(rèn)背景,而自定義布局會蓋上一層背景圖或背景色,導(dǎo)致默認(rèn)背景無用,帶來繪制性能損耗
- 去掉其他不必要的背景,減少背景重疊或覆蓋
- 多使用輕量級的ViewStub(只有設(shè)置可見或inflate時才會實例化內(nèi)部的布局),避免將所有View寫上,并動態(tài)控制GONE、VISIBLE
- 使用Merge,減少一層View層級
- 慎用Alpha,對一個View做Alpha轉(zhuǎn)化,需要先將View繪制出來,再做Alpha轉(zhuǎn)化,最后將轉(zhuǎn)換后效果繪制在界面上,也就是需要對當(dāng)前View繪制兩遍
3. Allocation Tracker
Android系統(tǒng)會依據(jù)內(nèi)存中不同的內(nèi)存數(shù)據(jù)類型分別執(zhí)行不同的GC操作,常見的導(dǎo)致GC頻繁執(zhí)行的原因主要可能是因為短時間內(nèi)有大量頻繁的對象創(chuàng)建與釋放操作,也就是俗稱的內(nèi)存抖動現(xiàn)象,或者短時間內(nèi)已經(jīng)存在大量內(nèi)存占用介于閾值邊緣,每當(dāng)有新對象創(chuàng)建時都會導(dǎo)致超越閾值觸發(fā)GC操作。
Allocation Tracker,內(nèi)存分配跟蹤器,可以記錄代碼運行過程中的內(nèi)存分配情況,包括已分配對象的調(diào)用棧、大小、代碼位置等,可以幫助我們發(fā)現(xiàn)在相同的調(diào)用棧中,短時間迅速分配與回收的大量相似對象,也可以幫助我們發(fā)現(xiàn)代碼中可能對內(nèi)存性能產(chǎn)生不良影響的地方。
1)打開Android Studio中的Android Monitor控制器,進入Memory內(nèi)存監(jiān)控窗口,點擊如下所示的Start Allocation Tracking按鈕,開始跟蹤

2)操作手機相關(guān)待檢測頁面,執(zhí)行相應(yīng)路徑代碼,此時Allocation Tracker會在后臺不斷記錄,注意操作時間不要過長,否則會產(chǎn)生過度的記錄,不便于發(fā)現(xiàn)問題。然后再點擊一次Start Allocation Tracking按鈕,停止跟蹤

3)最終會形成上圖所示的陰影區(qū)域,表示內(nèi)存跟蹤的時間段,然后會生存以.alloc命名的文件,默認(rèn)會以線程來分組

4)可選擇Group by Method或Group by Allocator,每組內(nèi)的數(shù)據(jù)默認(rèn)按照對象的分配順序排列,可點擊每條展開,并可最終跟蹤到最底層調(diào)用,Count表示分配的內(nèi)存的次數(shù),Size表示分配內(nèi)存的大小

5)若選擇Group by Allocator,則按照包名來分組,組內(nèi)排序和使用與上述相同

6)標(biāo)題欄有個統(tǒng)計按鈕,點擊后,可以生存炫酷的內(nèi)存分配輪胎圖或柱狀圖,默認(rèn)是輪胎圖,輪胎圖是以圓心為起點,最外層是其內(nèi)存實際分配的對象,每一個同心圓可能被分割成多個部分,代表了其不同的子孫,每一個同心圓代表他的一個后代,每個分割的部分代表了某一帶人有多人,你雙擊某個同心圓中某個分割的部分,會變成以你點擊的那一代為圓心再向外展開。如果想回到原始狀態(tài),雙擊圓心就可以了

4. TraceView
TraceView 是 Android 平臺特有的數(shù)據(jù)采集和分析工具,它主要用于分析 Android 中應(yīng)用程序的 hotspot。TraceView 本身只是一個數(shù)據(jù)分析工具,而數(shù)據(jù)的采集則需要使用 Android SDK 中的 Debug 類或者利用Android Device Monitor工具:
- 在一些關(guān)鍵代碼段開始前調(diào)用 Android SDK 中 Debug 類的 startMethodTracing 函數(shù),并在關(guān)鍵代碼段結(jié)束前調(diào)用 stopMethodTracing 函數(shù)。這兩個函數(shù)運行過程中將采集運行時間內(nèi)該應(yīng)用所有線程(注意,只能是 Java 線程)的函數(shù)執(zhí)行情況,并將采集數(shù)據(jù)保存到 /mnt/sdcard/ 下的一個文件中,然后利用 SDK 中的TraceView工具來分析這些數(shù)據(jù)
- 借助Android Device Monitor工具,采集系統(tǒng)中某個正在運行的進程的函數(shù)調(diào)用信息。對開發(fā)者而言,此方法適用于沒有目標(biāo)應(yīng)用源代碼的情況
1)打開Android Studio,進入Tools->Android->Android Device Monitor,選擇相關(guān)進程,并點擊Start Method Tracing按鈕,開始追蹤

2)操作應(yīng)用待檢測部分,不要時間太久,然后再次點擊Start Method Tracing按鈕,停止追蹤,便可自動生成.trace文件

TraceViewUI 劃分為上下兩個面板,Timeline Panel(時間線面板)和 Profile Panel(分析面板),Timeline Panel 又可細(xì)分為左右兩個 Panel:
左邊 Panel 顯示的是測試數(shù)據(jù)中所采集的線程信息
右邊 Pane 所示為時間線,時間線上是每個線程測試時間段內(nèi)所涉及的函數(shù)調(diào)用信息。這些信息包括函數(shù)名、函數(shù)執(zhí)行時間等
下半部分的Profile Panel 是 TraceView 的核心界面,主要展示了某個線程(先在 Timeline Panel 中選擇線程)中各個函數(shù)調(diào)用的情況,包括 CPU 使用時間、調(diào)用次數(shù)等信息。而這些信息正是查找 hotspot 的關(guān)鍵依據(jù)。下表是Profile Panel 中比較重要的列名及其描述:

可點擊上述任一排序項進行排序
3)雙擊任一條記錄,可展開詳細(xì)信息,包括調(diào)用者(Parents)和子函數(shù)(Children),可詳細(xì)的對調(diào)用次數(shù)過多的函數(shù)和每次執(zhí)行時間過長的函數(shù)做排查,便于發(fā)現(xiàn)HotSpot
二、布局優(yōu)化
1. 抽象布局標(biāo)簽
1)<include>標(biāo)簽
include標(biāo)簽常用于將布局中的公共部分提取出來供其他layout共用,以實現(xiàn)布局模塊化,這在布局編寫方便提供了大大的便利。
2)<viewstub>標(biāo)簽
viewstub標(biāo)簽同include標(biāo)簽一樣可以用來引入一個外部布局,但是,viewstub引入的布局默認(rèn)不會擴張,即既不會占用顯示也不會占用位置,從而在解析layout時節(jié)省cpu和內(nèi)存。viewstub常用來引入那些默認(rèn)不會顯示,只在特殊情況下顯示的布局,如進度布局、網(wǎng)絡(luò)失敗顯示刷新布局、信息出錯出現(xiàn)提示布局等。
3)<merge>標(biāo)簽
在使用了include后可能導(dǎo)致布局嵌套過多,多余不必要的layout節(jié)點,從而導(dǎo)致解析變慢,merge標(biāo)簽可用于兩種典型情況:
- 布局頂結(jié)點是FrameLayout且不需要設(shè)置background或padding等屬性,可以用merge代替,因為Activity內(nèi)容試圖的parent view就是個FrameLayout,所以可以用merge消除只剩一個
- 某布局作為子布局被其他布局include時,使用merge當(dāng)作該布局的頂節(jié)點,這樣在被引入時頂結(jié)點會自動被忽略,而將其子節(jié)點全部合并到主布局中
2. 去除不必要的嵌套和View節(jié)點
1)首次不需要使用的節(jié)點設(shè)置為GONE或使用viewstub
2)使用RelativeLayout代替LinearLayout
3. 減少不必要的infalte
1)對于inflate的布局可以直接緩存,用全部變量代替局部變量,避免下次需再次inflate
三、代碼優(yōu)化
1. 降低執(zhí)行時間
包括:緩存、數(shù)據(jù)存儲優(yōu)化、算法優(yōu)化、JNI、邏輯優(yōu)化等幾種優(yōu)化方式 。
1)緩存
緩存主要包括對象緩存、IO緩存、網(wǎng)絡(luò)緩存、DB緩存,對象緩存能減少內(nèi)存的分配,IO緩存減少磁盤的讀寫次數(shù),網(wǎng)絡(luò)緩存減少網(wǎng)絡(luò)傳輸,DB緩存較少Database的訪問次數(shù)。
在內(nèi)存、文件、數(shù)據(jù)庫、網(wǎng)絡(luò)的讀寫速度中,內(nèi)存都是最優(yōu)的,且速度數(shù)量級差別,所以盡量將需要頻繁訪問或訪問一次消耗較大的數(shù)據(jù)存儲在緩存中。
Android中常使用緩存:
- 線程池,對線程的緩存
- Android圖片緩存
- 消息緩存,通過handler.obtainMessage復(fù)用之前的message,如下:handler.sendMessage(handler.obtainMessage(0, object));
- ListView緩存
- 網(wǎng)絡(luò)緩存,數(shù)據(jù)庫緩存http response,根據(jù)http頭信息中的Cache-Control域確定緩存過期時間
- 文件IO緩存,使用具有緩存策略的輸入流,BufferedInputStream替代InputStream,BufferedReader替代Reader,BufferedReader替代BufferedInputStream.對文件、網(wǎng)絡(luò)IO皆適用
- layout緩存
- 其他需要頻繁訪問或訪問一次消耗較大的數(shù)據(jù)緩存
2)數(shù)據(jù)存儲優(yōu)化
包括數(shù)據(jù)類型、數(shù)據(jù)結(jié)構(gòu)的選擇:
- 數(shù)據(jù)類型選擇
字符串拼接用StringBuilder代替String,在非并發(fā)情況下用StringBuilder代替StringBuffer。
64位類型如long double的處理比32位如int慢。
使用SoftReference、WeakReference相對正常的強應(yīng)用來說更有利于系統(tǒng)垃圾回收。
final類型存儲在常量區(qū)中讀取效率更高。
枚舉值相比常量會占用更大的內(nèi)存空間和運行開銷,適用于強類型安全的場景,對于普通常量的匯總,就不一定需要。
盡量使用原始數(shù)據(jù)類型,避免頻繁的自動裝箱。
避免使用非靜態(tài)內(nèi)部類,當(dāng)創(chuàng)建并實例化了一個非靜態(tài)內(nèi)部類,內(nèi)部就包含一個指向外部類型的隱含引用,如果這個內(nèi)部類實例比外部類型存活的時間還長,那即使不需要這個外部類型,它還是會被保存在內(nèi)存中。
LocalBroadcastManager代替普通BroadcastReceiver,效率和安全性都更高。
如果對象中某個方法的調(diào)用不依賴于該對象的實例化,則建議將該方法定義成static,可提高訪問與調(diào)用效率。
- 數(shù)據(jù)結(jié)構(gòu)選擇
常見的數(shù)據(jù)結(jié)構(gòu)選擇如:
ArrayList和LinkedList的選擇,ArrayList隨機訪問更快,LinkedList更占內(nèi)存、隨機插入刪除更快速、擴容效率更高。
HashMap、LinkedHashMap、HashSet的選擇,HashMap為鍵值對數(shù)據(jù)結(jié)構(gòu),LinkedHashMap可以記住加入次序的hashMap,HashSet不允許重復(fù)元素。
HashMap、WeakHashMap選擇,WeakHashMap中元素可在適當(dāng)時候被系統(tǒng)垃圾回收器自動回收,所以適合在內(nèi)存緊張型中使用。
Collections.synchronizedMap和ConcurrentHashMap的選擇,ConcurrentHashMap為細(xì)分鎖,鎖粒度更小,并發(fā)性能更優(yōu)。Collections.synchronizedMap為對象鎖,自己添加函數(shù)進行鎖控制更方便。
Android也提供了一些性能更優(yōu)的數(shù)據(jù)類型,如SparseArray、SparseBooleanArray、SparseIntArray、Pair。
Sparse系列的數(shù)據(jù)結(jié)構(gòu)是為key為int情況的特殊處理,采用二分查找及簡單的數(shù)組存儲,加上不需要泛型轉(zhuǎn)換的開銷,相對Map來說性能更優(yōu)。
當(dāng)需要存儲一對元數(shù)據(jù)數(shù)組,例如(Foo,Bar),采用兩個平行的二維數(shù)組Foo[ ]和Bar[ ],要比直接存儲對象(Foo,Bar)數(shù)組的效率高。
使用增強的for-each循環(huán)對實現(xiàn)了iterable接口的collections以及數(shù)組做遍歷,for (Foo a : mArray)和for (int i = 0; i < len; ++i)效率最高,避免使用for (int i = 0; i < mArray.length; ++i)
3)算法優(yōu)化
這個主題比較大,需要具體問題具體分析,盡量不用O(n*n)時間復(fù)雜度以上的算法,必要時候可用空間換時間。查詢考慮hash和二分,盡量不用遞歸。
4)JNI
Android應(yīng)用程序大都通過Java開發(fā),需要編譯器將Java字節(jié)碼轉(zhuǎn)換成本地代碼運行,而本地代碼可以直接由設(shè)備管理器直接執(zhí)行,節(jié)省了中間步驟,所以執(zhí)行速度更快。不過需要注意從Java空間切換到本地空間需要開銷,同時編譯器也能生成優(yōu)化的本地代碼,所以糟糕的本地代碼不一定性能更優(yōu)。
5)邏輯優(yōu)化
主要是理清程序業(yè)務(wù)邏輯,減少不必要的操作和分支判斷等。
2. 異步,利用多線程提高TPS
充分利用多核CPU優(yōu)勢,利用線程解決密集型計算、IO、網(wǎng)絡(luò)等操作。
3. 提前或延遲操作,錯開時間段提高TPS
1)延遲操作
不在Activity、Service、BroadcastReceiver的生命周期等對響應(yīng)時間敏感函數(shù)中執(zhí)行耗時操作,可適當(dāng)delay,Java中延遲操作可使用ScheduledExecutorService, Android中除了支持ScheduledExecutorService之外,還有一些delay操作,如handler.postDelayed,handler.postAtTime,handler.sendMessageDelayed,View.postDelayed,AlarmManager定時等。
2)提前操作
對于第一次調(diào)用較耗時操作,可統(tǒng)一放到初始化中,將耗時提前。如得到壁紙wallpaperManager.getDrawable();
四、關(guān)于內(nèi)存泄漏
1. 使用Android Studio Java Heap Dump檢測
1)打開Android Studio,進入Android Device Monitor,切換到Memory監(jiān)控窗口
2)選擇待調(diào)試進程com.baidu.ls.waimai,并操作App中可能發(fā)生內(nèi)存泄漏的地方,點擊Initiate GC按鈕進行強制GC,然后點擊Dump Java Heap按鈕,導(dǎo)出.hprof格式文件

3)打開.hprof文件,可選擇Package Tree View,選擇應(yīng)用包內(nèi)想要查看的對象類型,可在右側(cè)Instance窗口查看該類型已存在的實例化對象數(shù)量,在下面Reference Tree窗口查看該對象引用路徑

4)上面窗口有個Total Count篩選項,可以看到該對象目前在內(nèi)存中存在的數(shù)量,若某個對象數(shù)量存在異常,比如此時App所有的點菜頁已關(guān)閉,但ShopMenuFragment數(shù)量不為0,則該對象很可能發(fā)生內(nèi)存泄漏,需要根據(jù)reference tree做相關(guān)排查,并找到最終的GC Root
2. 使用LeakCanary檢測
LeakCanary是一個用于檢測內(nèi)存泄露的開源類庫,提供了一種便捷、自動的檢測方式,并產(chǎn)出可視化報告,以很直白的方式將內(nèi)存泄露鏈條展示給我們。
1)接入,在build.gradle中根據(jù)不同的編譯方式,選擇加入不同的引用方式,
dependencies {
debugCompile 'com.squareup.leakcanary:leakcanary-android:1.3'
releaseCompile 'com.squareup.leakcanary:leakcanary-android-no-op:1.3'
}
2)LeakCanary.install(context) 會返回一個預(yù)定義的 RefWatcher,同時也會啟用一個 ActivityRefWatcher,用于自動監(jiān)控調(diào)用 Activity.onDestroy() 之后泄露的 activity。
在Application中進行配置:
public class ExampleApplication extends Application {
public static RefWatcher getRefWatcher(Context context) {
ExampleApplication application = (ExampleApplication) context.getApplicationContext();
return application.refWatcher;
}
private RefWatcher refWatcher;
@Override public void onCreate() {
super.onCreate();
refWatcher = LeakCanary.install(this);
}
}
3)使用RefWatcher監(jiān)控Fragment
public abstract class BaseFragment extends Fragment {
@Override public void onDestroy() {
super.onDestroy();
RefWatcher refWatcher = ExampleApplication.getRefWatcher(getActivity());
refWatcher.watch(this);
}
}
4)產(chǎn)出可視化報告

3. 常見避免內(nèi)存泄露方式
1)對Activity等組件的引用應(yīng)該控制在Activity的生命周期之內(nèi),如果不能就考慮使用getApplicationContext或者getApplication,以避免Activity被外部長生命周期的對象引用而泄露
2)盡量不要在靜態(tài)變量或者靜態(tài)內(nèi)部類中使用非靜態(tài)外部成員變量(包括
context ),即使要使用,也要考慮適時把外部成員變量置空;也可以在內(nèi)部類中使用弱引用來引用外部類的變量
3)對于生命周期比Activity長的內(nèi)部類對象,并且內(nèi)部類中使用了外部類的成員變量,可以這樣做避免內(nèi)存泄漏:將內(nèi)部類改為靜態(tài)內(nèi)部類、靜態(tài)內(nèi)部類中使用弱引用來引用外部類的成員變量
4)Handler持有的引用對象最好使用弱引用,資源釋放時也可以清空 Handler 里面的消息。比如在 Activity onStop 或者 onDestroy 的時候,取消掉該 Handler 對象的 Message和 Runnable
5)在 Java 的實現(xiàn)過程中,也要考慮其對象釋放,最好的方法是在不使用某對象時,顯式地將此對象賦值為 null,比如使用完Bitmap 后先調(diào)用 recycle(),再賦為null,清空對圖片等資源有直接引用或者間接引用的數(shù)組(使用 array.clear() ; array = null)等,最好遵循誰創(chuàng)建誰釋放的原則
6)正確關(guān)閉資源,對于使用了BraodcastReceiver,ContentObserver,F(xiàn)ile,游標(biāo) Cursor,Stream,Bitmap等資源的使用,應(yīng)該在Activity銷毀時及時關(guān)閉或者注銷
7)保持對對象生命周期的敏感,特別注意單例、靜態(tài)對象、全局性集合等的生命周期
六、參考鏈接
- Android官方性能優(yōu)化:
https://developer.android.com/training/best-performance.html - Android官方性能典范教程:
http://hukai.me/android-performance-patterns/ - 性能優(yōu)化博客合輯:
https://github.com/Juude/awesome-android-performance - Trinea性能優(yōu)化合輯:
http://www.trinea.cn/android/performance/ - Android性能優(yōu)化多途徑實現(xiàn):
http://blog.csdn.net/yanbober/article/details/48394201 - Android Studio官方profile工具使用:
https://developer.android.com/studio/profile/index.html - Android內(nèi)存泄露總結(jié):
https://yq.aliyun.com/articles/3009 - Android TraceView使用:
http://www.cnblogs.com/sunzn/p/3192231.html - LeakCanary使用:
http://www.itdecent.cn/p/7db231163168