1.gradle 引用
debugImplementation 'com.squareup.leakcanary:leakcanary-android:1.6.1' releaseImplementation 'com.squareup.leakcanary:leakcanary-android-no-op:1.6.1' //testCompile 'com.squareup.leakcanary:leakcanary-android-no-op:1.6.1'
2.使用
在自己的Application的onCreate()中调用
if (AppConfig.IS_DEBUG) {
refWatcher = LeakCanary.install(this);
}
AppConfig.IS_DEBUG是我定义的一个常量,在buildTypes进行赋值,进行自己来管理DEBUG状态
buildTypes {
release {
minifyEnabled false
signingConfig signingConfigs.debug
proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
buildConfigField "boolean", "IS_DEBUG", "false"
buildConfigField "boolean", "IS_LOG", "false"
}
debug {
signingConfig signingConfigs.debug
buildConfigField "boolean", "IS_DEBUG", "true"
buildConfigField "boolean", "IS_LOG", "true"
}
}
3.典型泄露
3.1查看泄露情况
简单情况下,是用了leakcanary,运行程序时会在测试机上安装一个
APP,可以在这里查看。

也可以通过,Android studio来查看详情,打开这个路径

打开后,找到设备中,对应APP的hprof文件

双击hprof文件,打开


打开分析,然后运行

就可以看到具体的泄漏情况了

3.2工具类静态变量,使用非Application上下文创建泄露
这是我定义的一个toast工具类,static Toaster mToaster;mToaster是static的,因为它的生命周期是跟随Application 的,如果使用activity之类来创建,就会在activity销毁后还保留该activity的引用,就导致了泄露。
public class Toaster {
private Toast mToast;
private Handler mHandler;
private TextView mText;
private Runnable lastRun;
private Toaster(){
Looper mainLooper = Looper.getMainLooper();
mHandler=new Handler(mainLooper);
}
private static Toaster mToaster;
public static Toaster getToaster(){
if (mToaster == null) {
mToaster=new Toaster();
}
return mToaster;
}
public void show(final String text){
if (!TextUtils.isEmpty(text)){
if (mToast == null) {
mToast=new Toast(App.instance);
LayoutInflater mInflate= (LayoutInflater) App.instance.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
View inflate = mInflate.inflate(R.layout.toast_layout, null);
mText = ((TextView) inflate.findViewById(R.id.message));
mToast.setView(inflate);
mToast.setDuration(Toast.LENGTH_SHORT);
//mToast.setGravity(Gravity.CENTER_HORIZONTAL,0,0);
}
if (lastRun != null) {
mHandler.removeCallbacks(lastRun);
}
mHandler.post(lastRun= new Runnable() {
@Override
public void run() {
mText.setText(text);
mToast.show();
}
});
}
}
}
3.3 MediaPlayer的内存泄漏
mediaPlayer使用,释放不正确导致泄露,正确的写法应该这样
if (mediaPlayer != null) {
mediaPlayer.stop();
/*查看了Mediaplayer的源码,发现存在一个引用,应该回收,但是在release方法中,并没有没处理,只有在reset方法中,这个引用才被消除。 */
mediaPlayer.reset();
mediaPlayer.release();
mediaPlayer = null;
}


LeakCanary内存泄漏检测
本文介绍如何使用LeakCanary进行内存泄漏检测,包括Gradle配置、在Application中初始化LeakCanary的方法及常见内存泄漏场景分析。
917

被折叠的 条评论
为什么被折叠?



