Square公司開發(fā)
可以直接在手機(jī)端查看內(nèi)存泄露的工具
實(shí)現(xiàn)原理:本質(zhì)上還是用命令控制生成hprof文件分析檢查內(nèi)存泄露郊闯,然后發(fā)送通知。
Application
? ???install()
LeakCanary
? ???androidWatcher()
RefWatcher
? ???new AndroidWatcherExecutor() --->dumpHeap()/analyze()(--->runAnalysis())-------->Hprof文件分析
? ???new AndroidHeapDumper()
? ???new ServiceHeapDumpListener
添加LeakCanary依賴包
https://github.com/square/leakcanary
在主模塊app下的build.gradle下添加如下依賴:
debugCompile 'com.squareup.leakcanary:leakcanary-android:1.3.1'
releaseCompile 'com.squareup.leakcanary:leakcanary-android-no-op:1.3.1'
開啟LeakCanary
-
添加Application子類
首先創(chuàng)建一個(gè)ExampleApplication迁央,該類繼承于Application,在該類的onCreate方法中添加如下代碼開啟LeakCanary監(jiān)控:
LeakCanary.install(this);
-
在配置文件中注冊(cè)ExampleApplication
在AndroidManifest.xml中的application標(biāo)簽中添加如下信息:
android:name=".ExampleApplication"
這個(gè)時(shí)候安裝應(yīng)用到手機(jī),會(huì)自動(dòng)安裝一個(gè)Leaks應(yīng)用乳幸,如下圖:
- **制造一個(gè)內(nèi)存泄漏的點(diǎn) **
建立一個(gè)ActivityManager類摔踱,單例模式,里面有一個(gè)數(shù)組用來保存Activity:
package com.example.android.sunshine.app;
import android.app.Activity;
import android.util.SparseArray;
import android.view.animation.AccelerateInterpolator;
import java.util.List;
public class ActivityManager {
private SparseArray<Activity> container = new SparseArray<Activity>();
private int key = 0;
private static ActivityManager mInstance;
private ActivityManager(){}
public static ActivityManager getInstance(){
if(mInstance == null){
mInstance = new ActivityManager();
}
return mInstance;
}
public void addActivity(Activity activity){
container.put(key++,activity);
}
}
然后在DetailActivity中的onCreate方法中將當(dāng)前activity添加到ActivityManager的數(shù)組中:
package com.example.android.sunshine.app;
import android.app.Activity;
import android.util.SparseArray;
import android.view.animation.AccelerateInterpolator;
import java.util.List;
public class ActivityManager {
private SparseArray<Activity> container = new SparseArray<Activity>();
private int key = 0;
private static ActivityManager mInstance;
private ActivityManager(){}
public static ActivityManager getInstance(){
if(mInstance == null){
mInstance = new ActivityManager();
}
return mInstance;
}
public void addActivity(Activity activity){
container.put(key++,activity);
}
}
我們從首頁(yè)跳轉(zhuǎn)到詳情頁(yè)的時(shí)候會(huì)進(jìn)入DetailActivity的onCreate的方法,然后就將當(dāng)前activity添加到了數(shù)組中寞缝,當(dāng)返回時(shí)癌压,我們沒把他從數(shù)組中刪除。再次進(jìn)入的時(shí)候荆陆,會(huì)創(chuàng)建新的activity 并添加到數(shù)組中滩届,但是之前的activity仍然被引用,無法釋放被啼,但是這個(gè)activity不會(huì)再被使用帜消,這個(gè)時(shí)候就造成了內(nèi)存泄漏。我們來看看LeakCanary是如何報(bào)出這個(gè)問題的浓体。
演示
解析的過程有點(diǎn)耗時(shí)泡挺,所以需要等待一會(huì)才會(huì)在Leaks應(yīng)用中,當(dāng)我們點(diǎn)開某一個(gè)信息時(shí)命浴,會(huì)看到詳細(xì)的泄漏信息: