Android使用Handler防止内存泄漏

作者: Brian512 | 来源:发表于2016-10-21 22:23 被阅读1136次

在Android开发中经常会使用handler做定时任务或者更新UI等,但是handler在好用的同时也是非常容易导致内存泄漏。因为handler在作为一个类的属性时会持有该类(通常是activity或fragment)的引用,而handler在发送message时,该message的target通常就是handler本身,也就是通过handler发送的消息间接持有该类的引用。当该类应当被回收,而消息队列中还有没处理的message时,该类也就无法被回收,从而导致了内存泄漏。这个场景是及其常见的,因为handler经常被用来发延时消息。
一个补救的办法就是在该类需要回收的时候,手动地把消息队列中的消息清空:

mHandler.removeCallbacksAndMessages(null);

这个方法用于有生命周期回调的组件中还好,稍微麻烦一点;若是在一个不知道该什么时候被回收的类里面,这个内存泄漏也是不可预测的。故而有下面的解决方案:

/**
 * 实现回调弱引用的Handler
 * 防止由于内部持有导致的内存泄露
 * 
 * PS:
 * 1、传入的Callback不能使用匿名实现的变量,必须与使用这个Handle的对象的生命周期一致,否则会被立即释放掉了
 * 
 * @author brian512
 */
public class WeakRefHandler extends Handler {
    private WeakReference<Callback> mWeakReference;
    
    public WeakRefHandler(Callback callback) {
        mWeakReference = new WeakReference<Handler.Callback>(callback);
    }
    
    public WeakRefHandler(Callback callback, Looper looper) {
        super(looper);
        mWeakReference = new WeakReference<Handler.Callback>(callback);
    }
    
    @Override
    public void handleMessage(Message msg) {
        if (mWeakReference != null && mWeakReference.get() != null) {
            Callback callback = mWeakReference.get();
            callback.handleMessage(msg);
        }
    }
}

由于是弱引用,当该类需要被回收时,就可以直接被回收掉。
WeakRefHandler的使用时如下:

    private Handler.Callback mCallback = new Handler.Callback() {
        @Override
        public boolean handleMessage(Message msg) {
            switch(msg.what){
            }
            return true;
        }
    };
    private Handler mHandler = new WeakRefHandler(mCallback);

CodeBlog是我做的一个编程技术学习客户端,集成了很多技术网站上的博客,应用宝详情页

相关文章

网友评论

  • 仿佛兮:大佬你好,这篇文章写的非常好,让我收获很多。但是我有一个问题想要问你。官方文档对CallBack接口有且只有这样一句描述:Callback interface you can use when instantiating a Handler to avoid having to implement your own subclass of Handler. 意思好像是Callback接口是用来实例Handler时避免写Handler的子类。但是在你的例子中CallBack接口并没有发挥这样的作用,这是为什么?

本文标题:Android使用Handler防止内存泄漏

本文链接:https://www.haomeiwen.com/subject/eevcuttx.html