天天看點

Android性能優化:阿裡、騰訊等關于記憶體洩露的知識都在這裡了

// 保證非靜态内部類的執行個體隻有1個

if (innerClass == null)

innerClass = new InnerClass();

}

// 非靜态内部類的定義    

private class InnerClass {        

//…

}

}

// 造成記憶體洩露的原因:

// a. 當TestActivity銷毀時,因非靜态内部類單例的引用(innerClass)的生命周期 = 應用App的生命周期、持有外部類TestActivity的引用

// b. 故 TestActivity無法被GC回收,進而導緻記憶體洩漏

  • 解決方案
  1. 将非靜态内部類設定為:靜态内部類(靜态内部類預設不持有外部類的引用)
  2. 該内部類抽取出來封裝成一個單例
  3. 盡量 避免 非靜态内部類所建立的執行個體 = 靜态
若需使用Context,建議使用 Application 的 Context

5.3.2 多線程:AsyncTask、實作Runnable接口、繼承Thread類

  • 儲備知識多線程的使用方法 = 非靜态内部類 / 匿名類;即 線程類 屬于 非靜态内部類 / 匿名類
  • 洩露原因當 工作線程正在處理任務 & 外部類需銷毀時, 由于 工作線程執行個體 持有外部類引用,将使得外部類無法被垃圾回收器(GC)回收,進而造成 記憶體洩露
多線程主要使用的是:AsyncTask、實作Runnable接口 & 繼承Thread類前3者記憶體洩露的原理相同,此處主要以繼承Thread類 為例說明

執行個體示範

public class MainActivity extends AppCompatActivity {

public static final String TAG = “carson:”;

@Override

public void onCreate(Bundle savedInstanceState) {

super.onCreate(savedInstanceState);

setContentView(R.layout.activity_main);

// 通過建立的内部類 實作多線程

new MyThread().start();

}

// 自定義的Thread子類

private class MyThread extends Thread{

@Override

public void run() {

try {

Thread.sleep(5000);

Log.d(TAG, “執行了多線程”);

} catch (InterruptedException e) {

e.printStackTrace();

}

}

}

}

public class MainActivity extends AppCompatActivity {

public static final String TAG = “carson:”;

@Override

public void onCreate(Bundle savedInstanceState) {

super.onCreate(savedInstanceState);

setContentView(R.layout.activity_main);

// 通過匿名内部類 實作多線程

new Thread() {

@Override

public void run() {

try {

Thread.sleep(5000);

Log.d(TAG, “執行了多線程”);

} catch (InterruptedException e) {

e.printStackTrace();

}

}

}.start();

}

}

// 工作線程Thread類屬于非靜态内部類 / 匿名内部類,運作時預設持有外部類的引用

// 當工作線程運作時,若外部類MainActivity需銷毀

// 由于此時工作線程類執行個體持有外部類的引用,将使得外部類無法被垃圾回收器(GC)回收,進而造成 記憶體洩露

  • 解決方案從上面可看出,造成記憶體洩露的原因有2個關鍵條件:
  1. 存在 ”工作線程執行個體 持有外部類引用“ 的引用關系
  2. 工作線程執行個體的生命周期 > 外部類的生命周期,即工作線程仍在運作 而 外部類需銷毀解決方案的思路 = 使得上述任1條件不成立 即可。

// 共有2個解決方案:靜态内部類 & 當外部類結束生命周期時,強制結束線程

// 具體描述如下

public class MainActivity extends AppCompatActivity {

public static final String TAG = “carson:”;

@Override

public void onCreate(Bundle savedInstanceState) {

super.onCreate(savedInstanceState);

setContentView(R.layout.activity_main);

// 通過建立的内部類 實作多線程

new MyThread().start();

}

// 分析1:自定義Thread子類

// 設定為:靜态内部類

private static class MyThread extends Thread{

@Override

public void run() {

try {

Thread.sleep(5000);

Log.d(TAG, “執行了多線程”);

} catch (InterruptedException e) {

e.printStackTrace();

}

}

}

}

@Override

protected void onDestroy() {

super.onDestroy();

Thread.stop();

// 外部類Activity生命周期結束時,強制結束線程

}

5.3.3 消息傳遞機制:HandlerAndroid 記憶體洩露:詳解 Handler 記憶體洩露的原因與解決方案https://www.jianshu.com/p/031515d8a7ca

5.4 資源對象使用後未關閉

  • 洩露原因對于資源的使用(如 廣播BraodcastReceiver、檔案流File、資料庫遊标Cursor、圖檔資源Bitmap等),若在Activity銷毀時無及時關閉 / 登出這些資源,則這些資源将不會被回收,進而造成記憶體洩漏
  • 解決方案在Activity銷毀時 及時關閉 / 登出資源

// 對于 廣播BraodcastReceiver:登出注冊

unregisterReceiver()

// 對于 檔案流File:關閉流

InputStream / OutputStream.close()

// 對于資料庫遊标cursor:使用後關閉遊标

cursor.close()

// 對于 圖檔資源Bitmap:Android配置設定給圖檔的記憶體隻有8M,若1個Bitmap對象占記憶體較多,當它不再被使用時,應調用recycle()回收此對象的像素所占用的記憶體;最後再賦為null 

Bitmap.recycle();

Bitmap = null;

// 對于動畫(屬性動畫)

// 将動畫設定成無限循環播放repeatCount = “infinite”後

// 在Activity退出時記得停止動畫

5.5 其他使用

  • 除了上述4種常見情況,還有一些日常的使用會導緻記憶體洩露
  • 主要包括:Context、WebView、Adapter,具體介紹如下
Android性能優化:阿裡、騰訊等關于記憶體洩露的知識都在這裡了

5.6 總結下面,我将用一張圖總結Android中記憶體洩露的原因 & 解決方案

6. 輔助分析記憶體洩露的工具

  • 哪怕完全了解 記憶體洩露的原因,但難免還是會出現記憶體洩露的現象
  • 下面将簡單介紹幾個主流的分析記憶體洩露的工具,分别是
  1. MAT(Memory Analysis Tools)
  2. Heap Viewer
  3. Allocation Tracker
  4. Android Studio 的 Memory Monitor
  5. LeakCanary

6.1 MAT(Memory Analysis Tools)

  • 定義:一個Eclipse的 Java Heap 記憶體分析工具 ->>下載下傳位址
  • 作用:檢視目前記憶體占用情況
通過分析 Java 程序的記憶體快照 HPROF 分析,快速計算出在記憶體中對象占用的大小,檢視哪些對象不能被垃圾收集器回收 & 可通過視圖直覺地檢視可能造成這種結果的對象

具體使用:MAT使用攻略

6.2 Heap Viewer

定義:一個的 Java Heap 記憶體分析工具作用:檢視目前記憶體快照

可檢視 分别有哪些類型的資料在堆記憶體總 & 各種類型資料的占比情況

具體使用:Heap Viewer使用攻略

6.3 Allocation Tracker

簡介:一個記憶體追蹤分析工具作用:追蹤記憶體配置設定資訊,按順序排列具體使用:Allocation Tracker使用攻略

6.4 Memory Monitor

簡介:一個 Android Studio 自帶 的圖形化檢測記憶體工具作用:跟蹤系統 / 應用的記憶體使用情況。核心功能如下

Android性能優化:阿裡、騰訊等關于記憶體洩露的知識都在這裡了

具體使用:Android Studio 的 Memory Monitor使用攻略

6.5 LeakCanary

簡介:一個square出品的Android開源庫 ->>下載下傳位址作用:檢測記憶體洩露具體使用:https://www.liaohuqiu.net/cn/posts/leak-canary/

7. 總結

本文 全面介紹了記憶體洩露的本質、原因 & 解決方案,希望大家在開發時盡量避免出現記憶體洩露

文章不易,如果大家喜歡這篇文章,或者對你有幫助希望大家多多點贊轉發關注哦。文章會持續更新的。絕對幹貨!!!

總結

最後為了幫助大家深刻了解Android相關知識點的原理以及面試相關知識,這裡放上相關的我搜集整理的14套騰訊、位元組跳動、阿裡、百度等2020面試真題解析,我把技術點整理成了視訊和PDF(實際上比預期多花了不少精力),包知識脈絡 + 諸多細節。

Android性能優化:阿裡、騰訊等關于記憶體洩露的知識都在這裡了
Android性能優化:阿裡、騰訊等關于記憶體洩露的知識都在這裡了
Android性能優化:阿裡、騰訊等關于記憶體洩露的知識都在這裡了
Android性能優化:阿裡、騰訊等關于記憶體洩露的知識都在這裡了

網上學習 Android的資料一大堆,但如果學到的知識不成體系,遇到問題時隻是淺嘗辄止,不再深入研究,那麼很難做到真正的技術提升。希望這份系統化的技術體系對大家有一個方向參考。

Android性能優化:阿裡、騰訊等關于記憶體洩露的知識都在這裡了

術體系](https://github.com/a120464/Android-P7/blob/master/Android%E5%BC%80%E5%8F%91%E4%B8%8D%E4%BC%9A%E8%BF%99%E4%BA%9B%EF%BC%9F%E5%A6%82%E4%BD%95%E9%9D%A2%E8%AF%95%E6%8B%BF%E9%AB%98%E8%96%AA%EF%BC%81.md)對大家有一個方向參考。

[外鍊圖檔轉存中…(img-LgdJXWl9-1646387697902)]

繼續閱讀