Android Handler导致内存泄漏的解决方案

最近一段时间,一直在优化项目,遇到了Handler导致的内存泄漏的问题,在解决之余,也发表一下自己的感想,希望对别人有点帮助。

在优化项目的时候,我发现很多人都喜欢用匿名内部类的方式创建一个Handler(当年我也这么写→_→)

private Handler mHandler = new Handler(){
    @Override
    public void handleMessage(Message msg) {
        super.handleMessage(msg);
    }
};

比较便捷,但是由于Java的内部类和匿名类会默认持有外部类的引用,如果Handler在等待发送延时消息的时候,Activity被finish,在Message被处理之前,Activity是无法被GC回收的,这就导致了Activity的内存泄漏,而且在Activity被finish之后,绝大多数情况handleMessage已经没有执行的必要了,但是这种方法获取的Handler依然会把这个Message执行下去,做了一些无用的操作而且还容易抛出异常。

网上有用static来修饰Handler来解决匿名类引用外部类的问题,虽然能解决引用外部类的情况,但是却增加了项目初始化的时间成本和方法区的空间,我并不太喜欢这种方式,而是采取了另一种外部类+软引用的方式解决这个问题,代码如下:

CustomHandler

/**
 * Description: TODO
 * author: Wang
 * date: 16/12/29 上午10:20
 * 
 * Copyright©2016 by wang. All rights reserved.
 */
public class CustomHandler extends Handler {

    private SoftReference<CustomHandleMessage> object;

    public CustomHandler(@NonNull CustomHandleMessage onHandleMessage) {
        object = new SoftReference(onHandleMessage);
    }

    @Override
    public void handleMessage(Message msg) {

        CustomHandleMessage onHandleMessage = object.get();
        if (onHandleMessage != null) {
            onHandleMessage.onHandler(msg);
        }
    }

    /**
     * 发送延时消息
     *
     * @param message
     * @param delayed
     */
    public void postDelayed(Message message, long delayed) {
        CustomRunnable runnable = new CustomRunnable(this, message);
        this.postDelayed(runnable, delayed);
    }
}

CustomHandleMessage

/**
 * Description: TODO
 * author: Wang
 * date: 16/12/29 下午10:10
 *
 * Copyright©2016 by wang. All rights reserved.
 */
public interface CustomHandleMessage {
    void onHandler(Message msg);
}

CustomRunnable

/**
 * Description: TODO
 * author: Wang
 * date: 16/12/29 下午10:08
 * 
 * Copyright©2016 by wang. All rights reserved.
 */
public class CustomRunnable implements Runnable {

    private CustomHandler handler;

    private Message message;

    public CustomRunnable(CustomHandler handler, Message message) {
        this.handler = handler;
        this.message = message;
    }

    @Override
    public void run() {
        handler.sendMessage(message);
    }
}

每个想要使用CustomHandler的类都要实现CustomHandleMessage接口,例如:

/**
 * Description: TODO
 * author: Wang
 * date: 11/28/16 11:08 AM
 * 
 * Copyright©2016 by wang. All rights reserved.
 */
public class TestActivity extends BaseActivity implements CustomHandleMessage {

    private CustomHandler handler = new CustomHandler(this);

    @Override
    public void onHandler(Message msg) {
        LogUtil.i(TAG, "msg  :  " + msg.what);
    }

    /**省略的方法**/
}

这样写的好处是,避免了Handler对外部类的引用,不再影响GC对外部类的回收。
打完收工。

PS:本猿也是最近才开始涉及Android内存的优化,有不足或错误的地方还请大家多多指正。

如果有用,顺手点个赞吧 O(∩_∩)O~~

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值