1. 程式人生 > >Android 使用LeakCanary 檢測記憶體洩露

Android 使用LeakCanary 檢測記憶體洩露

LeakCanary 是 Android 和 Java 記憶體洩露檢測框架,該框架是Square公司的一個開源庫,專案地址 leakcanary

Android 開發中你是否頻頻遇到記憶體洩露而無奈無從解決。說不定哪天你不小心寫的一行程式碼就導致了記憶體洩露。可以先看看這些問題導致的記憶體洩露 Android開發編碼規範導致的記憶體洩露問題,而LeakCanary 則很直白得檢測出了記憶體洩露並展示給我們。在使用它之前,我們來寫一個例子。

本地廣播,在開發中還是有一定的應用的,現在有這麼一個需求,要求使用本地廣播來實現,就是通過傳送一個退出程式的本地廣播,所有Activity接收到後就退出,這顯然是需要一個基礎的Activity,其他Activity繼承它。為了方便,這裡我們只使用一個Activity。

public class MainActivity extends AppCompatActivity {
    public final static String ACTION_EXIT_APP = "cn.edu.zafu.leakcanary.exit";
    private static LocalBroadcastManager mLocalBroadcatManager;
    private BroadcastReceiver mExitReceiver = new BroadcastReceiver() {

        @Override
        public
void onReceive(Context context, Intent intent) { String action = intent.getAction(); if (action.equals(ACTION_EXIT_APP)) { Log.d("TAG", "exit from broadcast"); finish(); } } }; @Override protected void onCreate(Bundle savedInstanceState) { super
.onCreate(savedInstanceState); setContentView(R.layout.activity_main); init(); } private void init() { IntentFilter filter = new IntentFilter(); filter.addAction(ACTION_EXIT_APP); filter.addCategory(Intent.CATEGORY_DEFAULT); getLocalBroadcastManager().registerReceiver(mExitReceiver, filter); } private LocalBroadcastManager getLocalBroadcastManager() { if (mLocalBroadcatManager == null) { mLocalBroadcatManager = LocalBroadcastManager.getInstance(this); } return mLocalBroadcatManager; } }

乍一看,是不是感覺寫的很對啊,那你就不夠細心了,這還是少量的程式碼,對於專案中日積月累的程式碼,記憶體洩露或許無處不在。我們使用LeakCanary 對我們的程式碼進行檢測下,看看到底哪裡發生了記憶體洩露,以及該如何解決。

使用方法也很簡單,首先加入依賴

debugCompile 'com.squareup.leakcanary:leakcanary-android:1.3.1'
releaseCompile 'com.squareup.leakcanary:leakcanary-android-no-op:1.3.1'

從依賴中也是可以看出貓膩的。

然後在我們程式的Applictaion中進行安裝,當然,不要忘記在清單檔案中註冊該Application。

public class App extends Application {
    @Override
    public void onCreate() {
        super.onCreate();
        LeakCanary.install(this);
    }
}

我說就這麼簡單你會信,好了,我們安裝到手機上看看。安裝完成後執行該軟體,開啟後退出該軟體,這時候你發現桌面上多了一個Leaks的圖示。

這裡寫圖片描述

開啟它後通知欄會有一個通知,通知你發生了記憶體洩露

這裡寫圖片描述

然後在軟體裡你會看到記憶體洩露的跟蹤資訊。

這裡寫圖片描述

點選下方的delete可以刪除此條資訊。

仔細一看,原來是我們的mLocalBroadcatManager發生了洩露,註冊本地廣播的時候,傳入了this,系統內部保持了這個引用,當我們退出Activity時,這個引用還是指向我們的Activity,導致Activity回收失敗。那麼怎麼解決了,既然退出的時候還持有引用,那麼我們取消註冊這個廣播這個引用不就沒了嗎,重寫onDestroy方法,進行取消註冊。

@Override
protected void onDestroy() {
    super.onDestroy();
    getLocalBroadcastManager().unregisterReceiver(mExitReceiver);
}

重新執行一下,咦,你發現記憶體不再洩露了。該軟體裡不再提示記憶體洩露的跟蹤資訊了。

這裡寫圖片描述

就是這麼簡單,如果想更進一步瞭解使用方法,比如檢測Fragment有沒有洩露。可以參考官方給的例子,並且記憶體洩露的跟蹤資訊也是可以上傳到伺服器的,更多內容,參考 leakcanary

原始碼下載