Android使用Handler防止内存泄漏

在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);
发布了124 篇原创文章 · 获赞 114 · 访问量 226万+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章