×

从一个Warning来聊聊Handler机制

96
CPPAlien
2017.03.11 00:27* 字数 366

如果直接在代码中如此实现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方法分发出去。

Android那些事儿
Web note ad 1