Android之LeakCanary使用教程

安卓开发,添加使用最常用的内存泄漏检测LeakCanary。内存泄漏同样也是安卓面试和开发中最常见的问题之一。

一直在使用这个检测内存泄漏,以前只是简单的集成,现在详细总结一下。

参考内存泄漏汇总:

集合类泄漏、单例造成的内存泄漏、非静态内部类创建静态实例造成的内存泄漏、Handler 造成的内存泄漏等。

集成LeakCanary方法:    Github中leakcanary代码

1.在module的build.gradle文件里添加依赖如下:

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

2.AndroidManifest.xml中添加权限 :(文末:Android6.0的权限动态申请





3.1.Android项目中,找到Application类(若没有,则新建并在AndroidManifest中声明),

在Application类onCreate()方法中添加如下代码:

if (LeakCanary.isInAnalyzerProcess(this)) {
    return;
}
LeakCanary.install(this);

但是,只能在Activity中进行内存泄漏检测。 

3.2.上述默认会检测Activity,但是不会去检测Fragment,若需要对某个Fragment检测,则需要以下代码:

//在自己的Application中添加如下代码
public static RefWatcher getRefWatcher(Context context) {
	App application = (App) context.getApplicationContext();
	return application.refWatcher;
}
 
private RefWatcher refWatcher;
@Override
public void onCreate() {
	super.onCreate();

	refWatcher = LeakCanary.install(this);
}
//在Activity中添加如下代码
@Override
protected void onCreate(Bundle savedInstanceState) {
	super.onCreate(savedInstanceState);
	setContentView(R.layout.activity_main);
	//初始时加入如下两行代码
	RefWatcher refWatcher = MyApp.getRefWatcher(this);
	refWatcher.watch(this);
    //... ...
}

4.检测某个特定的对象,如下代码:

假设对象为mObject

RefWatcher refWatcher = MyApp.getRefWatcher(this);
refWatcher.watch(mObject);

mObject这个对象还在内存中被其他对象引用,就会在 logcat 里看到内存泄漏的提示。

5.Android6.0中的配置

因为Android6.0的权限需要动态申请,不仅要在AndroidManifest.xml中添加权限,而且需要代码中动态申请:

动态申请的代码:

private static final int REQUEST_EXTERNAL_STORAGE = 1;
private static String[] PERMISSIONS_STORAGE = {
            "android.permission.READ_EXTERNAL_STORAGE",
            "android.permission.WRITE_EXTERNAL_STORAGE" };

public static void verifyStoragePermissions(Activity activity) {
    try {
        //检测是否有写的权限
        int permission = ActivityCompat.checkSelfPermission(activity,
                    "android.permission.WRITE_EXTERNAL_STORAGE");
        if (permission != PackageManager.PERMISSION_GRANTED) {
            // 没有写的权限,去申请写的权限,会弹出对话框
            ActivityCompat.requestPermissions(activity,
                           PERMISSIONS_STORAGE,REQUEST_EXTERNAL_STORAGE);
        }
    } catch (Exception e) {
            e.printStackTrace();
    }
}

在第一个Activity中调用:

protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        //申请权限
        verifyStoragePermissions(this);
}

6.LeakCanary实现原理:
监听:

在Android中,当一个Activity走完onDestroy生命周期后,说明该页面已经被销毁了,应该被系统GC回收。通过Application.registerActivityLifecycleCallbacks()方法注册Activity生命周期的监听,每当一个Activity页面销毁时候,获取到这个Activity去检测这个Activity是否真的被系统GC。

检测:

当获取了待分析的对象后,需要确定这个对象是否产生了内存泄漏。通过WeakReference + ReferenceQueue来判断对象是否被系统GC回收,WeakReference 创建时,可以传入一个ReferenceQueue 对象。当被 WeakReference 引用的对象的生命周期结束,一旦被 GC 检查到,GC 将会把该对象添加到 ReferenceQueue 中,待ReferenceQueue处理。当 GC 过后对象一直不被加入 ReferenceQueue,它可能存在内存泄漏。当我们初步确定待分析对象未被GC回收时候,手动触发GC,二次确认。

分析:
分析这块使用了Square的另一个开源库haha,https://github.com/square/haha,利用它获取当前内存中的heap堆信息的快照snapshot,然后通过待分析对象去snapshot里面去查找强引用关系。
 

你可能感兴趣的:(Android之开发框架)