如果直接在代码中如此实现Handler就会收到如下Warning,对于初学Android者来说可能无法理解为什么。
首先我们要知道所有的普通内部类都是持有外部类的引用的,而静态类不持有。你可以参考我写得另一篇文章《Android中常见的内存泄漏》。
可能有人觉得一个内部类持有外部类的引用太正常了,何必报warning。但此处的类是Handler,而Handler是有可能在该类的外部来执行的,也即生命周期与外部类不同步。比如我们看下面这段代码。
private mHandler = new Handler()
new Thread(new Runnable() {
@Override
public void run() {
Message msg = new Message();
Bundle bundle = new Bundle();
bundle.putString("key", "test");
msg.setData(bundle);
mHandler.sendMessageDelayed(msg, 6000);
}
}).start();
我们创建了一个线程,向mHandler
发送一个Message信息,而此消息将会在6秒后被执行,也即意味着只有在该消息被执行后,Handler引用才会被释放,然后它的外部类才能被释放。所以可能会造成内存泄漏。
我们再来说下Looper、MessageQueue、Handler这三者的作用和关系来让大家深入理解下上面的warning。每个Looper中都有一个MessageQueue,并且绑定到某个线程,Handler的作用是操作Message,Message是线程之间通信的消息格式。当某个线程中声明Handler后,如果未传入已有的Looper,默认会创建一个本线程下的Looper。通过某个Handler发送的消息来会进入对应的Looper中的MessageQueue中,而进入MessageQueue的消息会被Looper中的loop函数通过该Handler的dispatchMessage
方法分发出去。