Anroid Handler 内存泄漏问题

一般使用activity内使用handler发送延迟消息的时候 会使用以下代码

public class TestActivity extends Activity {
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);

        mHandler.sendEmptyMessageDelayed(0,3000);//3秒后发送消息
    }

    Handler mHandler = new Handler(new Handler.Callback() {
        @Override
        public boolean handleMessage(Message msg) {
            Log.e("activity","hahah");
            return true;
        }
    });
}

但是 如果 这个activity 在 mHandler发送消息的3秒内关闭的话就会造成 内存泄漏
为什么呢?
原因是 mHandler 这种非静态内部类 会自动持有一个 这个外部类 TestActivity 的实例对象,然而当 在消息还没 真正回调Log.e(“activity”,”hahah”);的时候,activity 已经关闭了,但是这个handler 还是绑定到当前的线程中,而mHandler 又持有TestActivity的引用,导致TestActivity 无法被GC 回收,导致内存泄漏

从网上看到的解决方案有两种
1. 在activity ondestory的时候 调用

        mHandler.removeCallbacksAndMessages(null);
        mHandler = null;

把当前 线程Looper 中 handler 相关的消息 remove掉,然后 解除 与TestActivity的引用,等待GC的回收

  1. 由于 上面的handler 使用的是 内部非静态类会自动持有外部类实例的 问题,可以通过 把他声明为 static 类,然后再通过 一个弱引用 (WeakReference)传入 activity(或者其他需要的参数)来让他允许GC来回收,like this
public class TestActivity extends Activity {
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        mHandler.sendEmptyMessageDelayed(0,3000);//3秒后发送消息
    }

    Handler mHandler = new MyHandler(this);

    private static class MyHandler extends Handler{
        WeakReference<Activity> mActivityWeakReference;

        public MyHandler(Activity activity){
            mActivityWeakReference = new WeakReference<Activity>(activity);
        }

        @Override
        public void handleMessage(Message msg) {
            Log.e("activity","hahah");
        }
    }
}

但是这里会出现一个问题 如果 这个activity单单是由handler持有引用还好,如果activity被其他对象引用到的话那就炸了。比如有个 UserModule 的成员变量 mActivity 引用了这个activity对象,那么用上面的方式是无法 被GC回收的。因为 GC 在回收 WeakReference 时,会检测这个对象是否有被其他对象强引用。如果有 那么就不会 回收这个对象,所以这个时候会一直卡在这里无法回收。

遇到的坑,在做个无限循环的 viewpager 做个幻灯片控件的时候,使用handler postDelayed 的方式,让他定期 去post 一个消息,达到会无限的动下去的效果,但是这里 的控件 不单被内部的handler 持有引用,而且在外部其他地方 比如activity中也持有这个 viewpager 的引用,导致这个时候 整个引用链相关的对象都无法被回收,这个时候 又不想在每个有使用到这个ViewPager 的activity,的onDestory中处理相关的引用(第一种解决方案),那么就在这个viewpager 的 onAttachedToWindow 和 onDetachedFromWindow 方法中对handler的 的处理。

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值