Android效能優化:帶你全面實現記憶體優化(文不如圖,圖不如表)
前言
在 Android開發中,效能優化策略十分重要
本文主要講解效能優化中的記憶體優化,希望你們會喜歡
目錄

1.png
1. 定義
優化處理 應用程式的記憶體使用、空間佔用
2. 作用
避免因不正確使用記憶體 & 缺乏管理,從而出現 記憶體洩露(ML)、記憶體溢位(OOM)、記憶體空間佔用過大 等問題,最終導致應用程式崩潰(Crash)
3. 儲備知識:Android 記憶體管理機制
3.1 簡介

1.png
下面,將針對回收 程序、物件 、變數的記憶體分配 & 回收進行詳細講解
3.2 針對程序的記憶體策略
a. 記憶體分配策略
由 ActivityManagerService 集中管理 所有程序的記憶體分配
b. 記憶體回收策略
步驟1:Application Framework 決定回收的程序型別
Android中的程序 是託管的;當程序空間緊張時,會 按程序優先順序低->>高的順序 自動回收程序
Android將程序分為5個優先等級,具體如下:

1.png
- 步驟2:Linux 核心真正回收具體程序
- ActivityManagerService 對 所有程序進行評分(評分存放在變數adj中)
- 更新評分到Linux 核心
- 由Linux 核心完成真正的記憶體回收
此處僅總結流程,這其中的過程複雜,有興趣的讀者可研究系統原始碼ActivityManagerService.java
3.3 針對物件、變數的記憶體策略
- Android的對於物件、變數的記憶體策略同 Java
- 記憶體管理 = 物件 / 變數的記憶體分配 + 記憶體釋放
下面,將詳細講解記憶體分配 & 記憶體釋放策略
a. 記憶體分配策略
-
物件 / 變數的記憶體分配 由程式自動 負責
-
共有3種:靜態分配、棧式分配、 & 堆式分配,分別面向靜態變數、區域性變數 & 物件例項
具體介紹如下
1.png
注:用1個例項講解 記憶體分配
public class Sample { // 該類的例項物件的成員變數s1、mSample1 & 指向物件存放在堆記憶體中 int s1 = 0; Sample mSample1 = new Sample(); // 方法中的區域性變數s2、mSample2存放在 棧記憶體 // 變數mSample2所指向的物件例項存放在 堆記憶體 public void method() { int s2 = 0; Sample mSample2 = new Sample(); } } // 變數mSample3的引用存放在棧記憶體中 // 變數mSample3所指向的物件例項存放在堆記憶體 // 該例項的成員變數s1、mSample1也存放在堆記憶體中 Sample mSample3 = new Sample();
b. 記憶體釋放策略
- 物件 / 變數的記憶體釋放 由Java垃圾回收器(GC) / 幀棧 負責
- 此處主要講解物件分配(即堆式分配)的記憶體釋放策略 = Java垃圾回收器(GC)
由於靜態分配不需釋放、棧式分配僅 通過幀棧自動出、入棧,較簡單,故不詳細描述
-
Java垃圾回收器(GC)的記憶體釋放 = 垃圾回收演算法,主要包括:
1.png
-
具體介紹如下
1.png
4. 常見的記憶體問題 & 優化方案
常見的記憶體問題如下
- 記憶體洩露
- 記憶體抖動
- 圖片Bitmap相關
- 程式碼質量 & 數量
- 日常不正確使用
下面,我將詳細分析每項的記憶體問題 & 給出優化方案
4.1 記憶體洩露
-
簡介
即 ML (Memory Leak),指 程式在申請記憶體後,當該記憶體不需再使用 但 卻無法被釋放 & 歸還給 程式的現象
-
對應用程式的影響
容易使得應用程式發生記憶體溢位,即 OOM
記憶體溢位 簡介:
1.png
-
發生記憶體洩露的本質原因
1.jpg
-
常見記憶體洩露原因
- 集合類
- Static關鍵字修飾的成員變數
- 非靜態內部類 / 匿名類
- 資源物件使用後未關閉
-
優化方案
具體請看文章: Android效能優化:關於 記憶體洩露 的知識都在這裡了!
4.2 圖片資源Bitmap相關
-
優化原因
即 為什麼要優化圖片Bitmap資源,具體如下圖:
1.png
-
優化方向
主要 從 以下方面優化圖片Bitmap資源的使用 & 記憶體管理
1.png
- 具體優化方案
下面,我將詳細講解每個優化方向的具體優化方案
關於更加具體的介紹,請看文章: Android 效能優化:手把手教你優化Bitmap圖片資源的使用

1.png
4.3 記憶體抖動
-
簡介
1.png
- 優化方案
儘量避免頻繁建立大量、臨時的小物件
4.4 程式碼質量 & 數量
-
優化原因
程式碼本身的質量(如 資料結構、資料型別等) & 數量(程式碼量的大小)可能會導致大量的記憶體問題,如佔用記憶體大、記憶體利用率低等
-
優化方案
主要從程式碼總量、資料結構、資料型別、 & 資料物件引用 方面優化,具體如下
1.png
4.5 常見使用
-
優化原因
一些常見使用也可能引發大量的記憶體問題,下面我將詳細介紹。
-
優化方案
1.png
還有1個記憶體優化的終極方案:調大 虛擬機器Dalvik的堆記憶體大小
即 在AndroidManifest.xml的application標籤中增加一個android:largeHeap屬性(值 = true),從而通知虛擬機器 應用程式需更大的堆記憶體,但不建議 & 不鼓勵該做法
4.6 額外小技巧
此處,還有一些記憶體優化的小技巧希望告訴給大家
- 技巧1:獲取當前可使用的記憶體大小
呼叫 ActivityManager.getMemoryClass()方法可獲取當前應用可用的記憶體大小(單位 = 兆) - 技巧2:獲取當前的記憶體使用情況
在應用生命週期的任何階段,呼叫 onTrimMemory()獲取應用程式 當前記憶體使用情況(以記憶體級別進行識別),可根據該方法返回的記憶體緊張級別引數 來釋放記憶體
Android 4.0 後提供的一個API

1.png
-
技巧3:當檢視變為隱藏狀態時,則釋放記憶體
當用戶跳轉到不同的應用 & 檢視不再顯示時, 應釋放應用檢視所佔的資源
1.注:此時釋放所佔用的資源能顯著的提高系統的快取處理容量
2.具體操作:實現當前Activity類的onTrimMemory()後,當用戶離開檢視時會得到通知;若得到返回的引數 = TRIM_MEMORY_UI_HIDDEN 即代表檢視變為隱藏狀態,則可釋放檢視所佔用的資源.
5. 輔助記憶體優化的分析工具
- 哪怕完全瞭解 記憶體的原因,但難免還是會出現人為難以發現的記憶體問題
- 下面將簡單介紹幾個主流的輔助分析記憶體優化的工具,分別是
- MAT(Memory Analysis Tools)
- Heap Viewer
- Allocation Tracker
- Android Studio 的 Memory Monitor
- LeakCanary
具體使用看記憶體洩漏那篇文章。
6. 總結
本文主要講解記憶體優化的相關知識,總結如下:

1.png