原因:
Handler 的使用造成的内存泄漏问题应该说是最为常见了,很多时候我们为了避免 ANR 而不在主线程进行耗时操作,在处理网络任务或者封装一些请求回调等api都借助Handler来处理,但 Handler 不是万能的,对于 Handler 的使用代码编写一不规范即有可能造成内存泄漏。另外,我们知道 Handler、Message 和 MessageQueue 都是相互关联在一起的,万一 Handler 发送的 Message 尚未被处理,则该 Message 及发送它的 Handler 对象将被线程 MessageQueue 一直持有。
由于 Handler 属于 TLS(Thread Local Storage) 变量, 生命周期和 Activity 是不一致的。因此这种实现方式一般很难保证跟 View 或者 Activity 的生命周期保持一致,故很容易导致无法正确释放。
分析:
对于handler泄漏其实是由于消息队列持有对handler的引用,而handler又持有activity的隐式引用,这个引用会保持到消息得到处理,而导致activity无法被垃圾回收器进行回收,而导致内存泄漏 ,使用static+WeakReference可以解决内存泄漏问题,不过不写也无所谓 , 不加static的默认会在handler构造函数加上activity这个参数,只要handler没有被回收,就会泄露。加static目的是为了防止泄露,为什么会泄露,就是因为没回收,没回收是因为还引用着。只有postDelayed的时候才会有泄露问题,因为delayed的时候activity的引用还保持着,所以只要delayed完了就能回收了,大多数情况下根本不必用加static。
说了这么多搬砖好,下面呈上如何搬好砖:
import android.app.Activity;
import android.os.Handler;
import android.os.Message;
import java.lang.ref.WeakReference;
/**
* Description Handler内存泄漏的处理类
* Created by
* Date
*/
public class MyHandler extends Handler {
private WeakReference<Activity> mActivity;
private HandleMessageCallBack handleMessageCallBack;
public MyHandler(Activity activity, HandleMessageCallBack handleMessageCallBack) {
mActivity = new WeakReference<>(activity);
this.handleMessageCallBack = handleMessageCallBack;
}
@Override
public void handleMessage(Message msg) {
Activity activity = mActivity.get();
if (activity != null) {
//做操作
handleMessageCallBack.messageCallBack(msg);
}
}
//接口回调Message
public interface HandleMessageCallBack {
void messageCallBack(Message msg);
}
}