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
原始碼下載