本篇重點是效能優化,包括內容:
- 佈局優化
- 繪製優化
- 記憶體洩漏優化
- MAT工具
- 響應速度優化
- ListView優化
- Bitmap優化
- 執行緒優化
- 其他
1.佈局優化
a.核心思想:儘量減少佈局檔案的層級。
b.方式:
- 多巢狀情況下可使用RelativeLayout減少巢狀。
- 佈局層級相同的情況下使用LinearLayout,它比RelativeLayout更高效。
- 使用
<include>
標籤重用佈局、<merge>
標籤減少層級、<ViewStub>
標籤懶載入。詳見佈局篇--佈局原則
補充例項: Android最佳效能實踐--佈局優化技巧
2.繪製優化
a.核心思想:避免在View.onDraw()
中執行大量的操作。
b.方式:
- 避免建立新的區域性物件,因為
onDraw()
可能被多次呼叫而產生大量的臨時物件,導致佔用過多記憶體、系統頻繁gc,降低了執行效率。 - 避免做耗時任務,以及大量迴圈操作。
3.記憶體洩漏優化
a.記憶體洩漏(Memory Leak):程式在申請記憶體後,無法釋放已申請的記憶體空間。是造成應用程式OOM的主要原因之一。
記憶體溢位(out of memory):指程式在申請記憶體時,沒有足夠的記憶體空間供其使用。
補充閱讀:記憶體溢位和記憶體洩漏的區別
b.可能原因:
- 靜態變數導致的記憶體洩漏
- 詳情:一個靜態變數又是非靜態內部類會一直持有對外部類的引用,導致外部類Activity無法被回收。
- 解決辦法:將內部類設為靜態內部類或獨立出來;使用
context.getApplicationContext()
。
- 單例模式導致的記憶體洩漏
- 詳情:單例傳入引數this來自Activity,使得持有對Activity的引用。
- 解決辦法:傳參
context.getApplicationContext()
。
- 屬性動畫導致的記憶體洩漏
- 詳情:沒有在
onDestroy()
中停止無限迴圈的屬性動畫,使得View持有了Activity。 - 解決辦法:在
Activity.onDestroy()
中呼叫Animator.cancel()
停止動畫。
- 詳情:沒有在
- Handler導致的記憶體洩漏
- 詳情:Message持有對Handler的引用,而非靜態內部類的Handler又隱式持有對外部類Activity的引用,使得引用關係會保持至訊息得到處理,從而阻止了Activity的回收。
- 解決辦法:使用靜態內部類+WeakReference弱引用;當外部類結束生命週期時清空訊息佇列。
- 執行緒導致的記憶體洩漏
- 詳情:AsyncTask/Runnable以匿名內部類的方式存在,會隱式持有對所在Activity的引用。
- 解決辦法:將AsyncTask和Runnable設為靜態內部類或獨立出來;線上程內部採用弱引用儲存Context引用。
- 資源未關閉導致的記憶體洩漏
- 詳情:未及時登出資源導致記憶體洩漏,如BraodcastReceiver、File、Cursor、Stream、Bitmap等。
- 解決辦法:在Activity銷燬的時候要及時關閉或者登出。
- BraodcastReceiver:呼叫
unregisterReceiver()
登出; - Cursor,Stream、File:呼叫
close()
關閉; - Bitmap:呼叫
recycle()
釋放記憶體(2.3版本後無需手動)。
- BraodcastReceiver:呼叫
- Adapter導致的記憶體洩漏
- 詳情:不使用快取而只依靠
getView()
每次重新例項化Item,會給gc製造壓力。 - 解決辦法:在構造Adapter時使用快取的convertView。
- 詳情:不使用快取而只依靠
c.方式:
- 在開發過程中避免寫出記憶體洩漏的程式碼,可參考以上多種解決辦法。
- 通過分析工具如MAT尋找潛在的記憶體洩漏。
推薦閱讀:常見的記憶體洩漏原因及解決方法
4.響應速度優化
a.核心思想:避免在主執行緒中做耗時操作。
b.方式:開執行緒。
5.ListView優化
- 複用ViewHolder,具體使用;
- 不要在
getView()
中執行耗時操作; - 開啟硬體加速。
綜合例項:ListView終極優化方法
6.Bitmap優化
- 利用BitmapFactory.Options的inSampleSize屬性,根據需求對圖片進行取樣後再載入進來。詳見Bitmap的高效載入
7.執行緒優化
- 採用執行緒池,避免存在大量的Thread。詳見執行緒&執行緒池
8.其他
- 避免建立過多的物件 ;
- 不要過多使用列舉,列舉佔用的記憶體空間要比整型大;
- 常量請使用static final來修飾;
- 使用一些Android特有的資料結構,比如SparseArray和Pair等,它們都具有更好的效能;
- 適當使用軟引用和弱引用;
- 採用記憶體快取和磁碟快取;
- 儘量採用靜態內部類,這樣可以避免潛在的由於內部類而導致的記憶體洩露。
推薦閱讀:Android開發效能優化總結、 Android最佳效能實踐系列
最後,是有助於提高程式可維護性的幾點建議,一起共勉:
希望這篇文章對你有幫助~