Android内存优化LeakCanary使用详解

1.概述

如果使用MAT来分析内存问题,会有一些难度,并且效率也不是很高,对于一个内存泄漏问题,可能要进行多次排查和对比。

为了能够简单迅速的发现内存泄漏,Square公司基于MAT开源了LeakCanary。

2.使用LeakCanary

首先配置build.gradle:

dependencies {

  debugCompile 'com.squareup.leakcanary:leakcanary-android:1.5.2'

  releaseCompile 'com.squareup.leakcanary:leakcanary-android-no-op:1.5.2'

}

接下来在Application加入如下代码。

public class LeakApplication extends Application {

    @Override public void onCreate() {

    super.onCreate();

    if (LeakCanary.isInAnalyzerProcess(this)) {//1

      // This process is dedicated to LeakCanary for heap analysis.

      // You should not init your app in this process.

      return;

    }

    LeakCanary.install(this);

  }

}

注释1处的代码用来进行过滤操作,如果当前的进程是用来给LeakCanary 进行堆分析的则return,否则会执行LeakCanary的install方法。这样我们就可以使用LeakCanary了,如果检测到某个Activity 有内存泄露,LeakCanary 就会给出提示。

3.LeakCanary应用举例

第二节的例子代码只能够检测Activity的内存泄漏,当然还存在其他类的内存泄漏,这时我们就需要使用RefWatcher来进行监控。改写Application,如下所示。

public class LeakApplication extends Application {

    private RefWatcher refWatcher;

    @Override

    public void onCreate() {

        super.onCreate();

        refWatcher= setupLeakCanary();

    }

    private RefWatcher setupLeakCanary() {

        if (LeakCanary.isInAnalyzerProcess(this)) {

            return RefWatcher.DISABLED;

        }

        return LeakCanary.install(this);

    }

    public static RefWatcher getRefWatcher(Context context) {

        LeakApplication leakApplication = (LeakApplication) context.getApplicationContext();

        return leakApplication.refWatcher;

    }

}

install方法会返回RefWatcher用来监控对象,LeakApplication中还要提供getRefWatcher静态方法来返回全局RefWatcher。

最后为了举例,我们在一段存在内存泄漏的代码中引入LeakCanary监控,如下所示。

public class MainActivity extends AppCompatActivity {

    @Override

    protected void onCreate(Bundle savedInstanceState) {

        super.onCreate(savedInstanceState);

        setContentView(R.layout.activity_main);

        LeakThread leakThread = new LeakThread();

        leakThread.start();

    }

    class LeakThread extends Thread {

        @Override

        public void run() {

            try {

                Thread.sleep(6 * 60 * 1000);

            } catch (InterruptedException e) {

                e.printStackTrace();

            }

        }

    }

    @Override

    protected void onDestroy() {

        super.onDestroy();

        RefWatcher refWatcher = LeakApplication.getRefWatcher(this);//1

        refWatcher.watch(this);

    }

}

MainActivity存在内存泄漏,原因就是非静态内部类LeakThread持有外部类MainActivity的引用,LeakThread中做了耗时操作,导致MainActivity无法被释放。关于内存泄漏可以查看Android内存优化(三)避免可控的内存泄漏这篇文章。

在注释1处得到RefWatcher,并调用它的watch方法,watch方法的参数就是要监控的对象。当然,在这个例子中onDestroy方法是多余的,因为LeakCanary在调用install方法时会启动一个ActivityRefWatcher类,它用于自动监控Activity执行onDestroy方法之后是否发生内存泄露。这里只是为了方便举例,如果想要监控Fragment,在Fragment中添加如上的onDestroy方法是有用的。

运行程序,这时会在界面生成一个名为Leaks的应用图标。接下来不断的切换横竖屏,这时会闪出一个提示框,提示内容为:“Dumping memory app will freeze.Brrrr.”。再稍等片刻,内存泄漏信息就会通过Notification展示出来

你可能感兴趣的:(Android内存优化LeakCanary使用详解)