Android使用Handler防止内存泄漏
2016-10-21 本文已影响1136人
Brian512
在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);