LeakCanary (Android 檢測內存泄漏工具的使用)

LeakCanary是andrid 檢測內存泄漏的工具,使用起來比MAT方便很多


下面介紹LeakCanary 的使用
下面是在在androidStudio 中使用
首先 在 build.gradle 中加入引用,不同的編譯使用不同的引用:

dependencies {
    debugCompile 'com.squareup.leakcanary:leakcanary-android:1.3.1' // or 1.4-beta1
    releaseCompile 'com.squareup.leakcanary:leakcanary-android-no-op:1.3.1' // or 1.4-beta1
    testCompile 'com.squareup.leakcanary:leakcanary-android-no-op:1.3.1' // or 1.4-beta1
}

在Application 中使用,用於檢測所有Activity的內存泄漏狀況,只需要在Application onCreate()方法中添加LeakCanary.install(this); 一行代碼就ok了

public class MyApplication extends Application{

    public static RefWatcher getRefWatcher(Context context) {

    @Override
    public void onCreate() {
        super.onCreate();
        LeakCanary.install(this);
    }
}

還可以檢測那些本該被回收的對象,使用RefWatcher
RefWatcher 用於:
1. 檢測調用 Activity.onDestroy() 之後泄露的 activity
2. 檢測 Fragment


檢測調用 Activity.onDestroy() 之後泄露的 activity

LeakCanary.install() 會返回一個預定義的 RefWatcher,同時也會啓用一個 ActivityRefWatcher,用於自動監控調用 Activity.onDestroy() 之後泄露的 activity。

public class MyApplication extends Application{

    public static RefWatcher getRefWatcher(Context context) {
        MyApplication application = (MyApplication) context.getApplicationContext();
        return application.refWatcher;
    }

    private RefWatcher refWatcher;


    @Override
    public void onCreate() {
        super.onCreate();
        refWatcher = LeakCanary.install(this);
    }
}

使用 RefWatcher 監控 Fragment

因爲它和Activity實例一樣可能持有大量的視圖以及視圖需要的資源(比如Bitmap)即在Fragment onDestroy方法中加入如下實現,使用refWatcher.watch(Object o)監控Fragmeng對象

public abstract class BaseFragment extends Fragment {

    @Override public void onDestroy() {
        super.onDestroy();
        RefWatcher refWatcher = MyApplication.getRefWatcher(getActivity());
        refWatcher.watch(this);
    }
}

模擬內存泄漏

public class TestDataModel {

    private static TestDataModel sInstance;
    private TextView mRetainedTextView;

    public static TestDataModel getInstance() {
        if (sInstance == null) {
            sInstance = new TestDataModel();
        }
        return sInstance;
    }

    public void setRetainedTextView(TextView textView) {
        mRetainedTextView = textView;
    }
}

然後在Activity 和 Fragment 中分別調用

TextView textview = (TextView)view.findViewById(R.id.textview);    TestDataModel.getInstance().setRetainedTextView(textview);

然後就可以運行程序了,別忘了MyApplication 在清單文件中聲明

當檢測到內存泄漏後,在通知欄中會以通知的形式通知
點進去查看詳情
如圖:
LeakCanary 內存泄露詳情頁面
可以詳細的看到哪個包中的哪個類哪個變量引起的內存泄漏,很直觀

如果想要監控某個可能存在內存泄漏的對象

MyApplication.getRefWatcher().watch(sLeaky);//sLeaky 爲要監控的對象

其他也可以監控的對象

BroadcastReceiver
Service
其他有生命週期的對象
直接間接持有大內存佔用的對象(即Retained Heap值比較大的對象)


SDK 導致的內存泄露

在檢測出內存泄漏中,我們甚至可以看到sdk的內存泄漏
隨着時間的推移,很多SDK 和廠商 ROM 中的內存泄露問題已經被儘快修復了。但是,當這樣的問題發生時,一般的開發者能做的事情很有限。

LeakCanary 有一個已知問題的忽略列表,AndroidExcludedRefs.java,如果你發現了一個新的問題,請提一個 issue 並附上 leak trace, reference key, 機器型號和 SDK 版本。如果可以附帶上 dump 文件的 鏈接那就再好不過了。

對於最新發布的 Android,這點尤其重要。你有機會在幫助在早期發現新的內存泄露,這對整個 Android 社區都有極大的益處。

如何不影響對外版APK

可以看出我們在引入依賴時,都已經區分開了

debugCompile 'com.squareup.leakcanary:leakcanary-android:1.3.1' // or 1.4-beta1
    releaseCompile 'com.squareup.leakcanary:leakcanary-android-no-op:1.3.1' // or 1.4-beta1
    testCompile 'com.squareup.leakcanary:leakcanary-android-no-op:1.3.1' // or 1.4-beta1

debugCompile、releaseCompile、testCompile 提供了三種不同的模式

其中releaseCompile和testCompile這兩個的依賴明顯不同於debugCompile的依賴。它們的依賴屬於NOOP操作。

NOOP,即No Operation Performed,無操作指令。常用的編譯器技術會檢測無操作指令並出於優化的目的將無操作指令剔除。

因而,只要配置好releaseCompile和testCompile的依賴,就無需擔心對外版本的性能問題了

demo

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章