leakcanary的使用以及常见的泄露

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;
}

 

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值