您的位置:首页 > 其它

Handler源码解析

2016-06-07 11:13 162 查看
通常我们使用Handler时,直接在activity直接new handler使用,但是在子线程中并不能直接new 让然后使用。如果直接在子线程中直接new  ,会出现如下的错误提示:



意思就是说:在没有调用Looper.prepare()之前不能在子线程创建Handler。

为什么在主线程中我们就已经可以直接创建Handler?


因为在Activity的启动代码中,已经在当前UI线程(主线程)调用了Looper.prepareMainLooper()和Looper.loop()方法。我们可以在源码的ActivityThread类中看到,如图:






从上图可以看出,在主线程中首先调用的是Looper.prepareMainLooper(),然后创建了一个ActivityThread实例,最后通过Looper类使主线程进入消息循环中。

如果在子线程中使用handler,必须要调用loop.prepare()和looper.loop()方法。

那这2个方法到底做了哪些事呢?

首先说Looper.prepare()



在调用 Looper.prepare() 方法时,创建一个 Looper 对象,这个对象是被 set 绑定到一个ThreadLocal(线程局部变量)中。

sThreadLocal.set(new Looper(quitAllowed));  ThreadLocal的作用就是保证每一个调用了prepare()函数的线程里面都有一个唯一的Looper对象。

而new Looper(quitAllowed)方法实际上也创建了消息队列MessageQueue,如下图:



再来说Looper.loop()






以下还有剩余未截全的,承接上面的






可以看出,这个方法就是不断从消息队列(MessageQueue)中取出消息,再调用handler.dispatchMessage()分发消息,如下图:






这个handleMessage方法就是我们使用handler时,经常重写的方法。

当然有些人说,在Loop.loop()方法中msg.target.dispatchMessage(msg),你怎么确定是handler的dispatchMessage方法呢?好吧,让你看下Message类中成员变量,如下图:






最后,有人会问,消息(Message)既然是从消息队列(MessageQueue)中取出来的,那消息(Message)是从哪进入消息队列(MessageQueue)的呢?

如下一组图:















直到最后一张图才看到,queue.enqueueMessage(msg, uptimeMillis);这就是消息进入消息队列的方法。

不管handler调用哪个方法发送消息,最终都会调用queue.enqueueMessage(msg, uptimeMillis);
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: