android 内存溢出检查,Android Handler使用导致内存溢出附带LeakCanary排查

最近项目马上结束了在对项目进行检查有没有内存泄漏的地方,这里使用的是leakcanary。

使用步骤很简单:

添加依赖:

dependencies { debugCompile 'com.squareup.leakcanary:leakcanary-android:1.4-beta2' releaseCompile 'com.squareup.leakcanary:leakcanary-android-no-op:1.4-beta2' testCompile 'com.squareup.leakcanary:leakcanary-android-no-op:1.4-beta2' }

配置Application

@Override

public void onCreate() {

super.onCreate();

LeakCanary.install(this);

}}```

这是github上的网址:https://github.com/square/leakcanary

下面是检测出来的结果。![这里写图片描述](http://upload-images.jianshu.io/upload_images/1711057-6570c583e431052f?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240)

这是一个提醒框,提醒用户正在加载中。仔细查看了下代码能导致内存溢出的只有这一行代码。

``` public LoadingDialog getDialog(String info) {

Builder b = new Builder(mContext);

b.setInfo(info);

dialog = b.create();

dialog.show();

UIUtils.postDelayed(new Runnable() {

@Override

public void run() {

if (dialog.isShowing()) {

dialog.dismiss();

MlsApplication.showToast("操作超时,请稍后再试"); } } }, 10000);

return dialog; }```

这里是调用的Handler中的postDelayed()方法延时执行某个动作。这里有这样一层关系Dialog创建时的参数有Activity的Context所以dialog中有context的引用,又因为handler持有外部类的引用,为什么持有呢?

摘抄一段话:

1. 当一个Android应用启动时,框架会分配到一个Looper实例给应用的主线程。这个Looper的主要工作就是处理一个接着一个的消息对象。在Android中,所有Android框架的事件(比如Activity的生命周期方法的调用和按钮的点击等)都是放到消息中,然后加入到Looper要处理的消息队列中,由Looper依次处理。主线程的Looper的生命周期和应用的一样长。

2. 当在主线程中初始化一个Handler时,它就会关联到Looper的消息队列。发送到消息队列的消息本身就持有Handler的引用,只有这样Looper在处理这个条消息的时候才能调用Handler#handleMessage(Message)处理消息。

3. 在Java中,非静态的内部类和匿名内部类都会隐式地持有其外部类的引用。而静态的内部类则不会。

链接:http://johnnyshieh.github.io/android/2015/09/03/android-handler-memory-leak/

其中runnable使用的是匿名内部类也持有外部类的引用,这就引发了一个问题当Activity finish的时候因为还有其他类对Activity持有引用就不会导致Activity从内存中销毁最后就会引发内存泄漏。下面是解决办法:因为静态类是不会持有外部类的引用,但是会有一个问题?怎么在静态内部类中使用外部类的变量呢?这里就要使用弱引用WeakReference.

1.首先创建一个静态的handler

``` private static class MyHandler extends Handler {

private final WeakReference mActivity;

private MyHandler(Context mActivity) {

this.mActivity = new WeakReference(mActivity);

}

}```

2.创建一个静态的Runnable

``` private static final class WeakRunnable implements Runnable {

private WeakReference dialog;

public WeakRunnable(Dialog dialog) {

this.dialog =new WeakReference < Dialog > (dialog);

}

@Override

public void run() {

Dialog dialog = this.dialog.get();

if (null != dialog && dialog.isShowing()) {

dialog.dismiss(); } } }```

3.修改调用

``` handler.postDelayed(new WeakRunnable(dialog), 100000);```

这样在重新运行程序连续切换界面旋转屏幕都不会出现内存泄漏了。

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值