Android 的线程间通信主要是通过 Handler 来实现,那么具体是怎么实现运转的呢?下面就从源码的角度进行分析。
首先从英文字面上这几个单词可以理解为 Handler(执行者),Looper(循环者),Message(消息),MessageQuene(消息队列)。
Looper
我们在子线程使用 Handler 的时候一定要调用 Looper 的以下两个函数(主线程默认已经调用了这两个函数):
|
|
looper.prepare()
|
|
在 prepare() 方法中,我们看到了一个全局变量 ThreadLocal。ThreadLocal 是一个线程内部的数据存储类,在 Handler 的运行机制中具有很重要的作用,它可以在指定的线程中存储数据,数据存储后,只有在指定线程中可以获取到存储的数据,对于其他线程来说无法获取到数据。对于 Handler 来说,它需要获取当前线程的 Looper,这个时候通过 ThreadLocal 就能轻松实现 Looper 在当前线程中的获取。
在 prepare() 函数中,当前线程下 ThreadLocal 如果取不到 Looper 对象,便会在 ThreadLocal 中创建一个当前线程下的 Looper。继续看 Looper 的构造函数
|
|
可以发现 Looper 内维护了一个消息队列和一个线程。
looper.loop()
|
|
在 loop() 方法中可以看到又一个 for 循环,循环每次都从 MessageQuene 中取出 Message,当取出的 Message 为空的时候就直接 return 掉,否则执行 msg.target.dispatchMessage(msg)(分发该消息,msg.target 是什么待会再说)。
Handler
Handler 在发送消息的时候有许多种方法,大多都是要通过 sendMessageAtTime() 发送。
|
|
enqueueMessage() 方法代码如下:
|
|
可以看到 Message 正是在这个方法内被 Handler 装进了 MessageQuene。更让人激动的是我们发现了 msg.target = this 这行代码,这也就意味着在 Looper 的 loop() 方法中,msg.target.dispatchMessage(msg) 表示执行消息分发的是 Handler。我们再去 Handler 中搜索 dispatchMessage() 方法。
|
|
发现了我们熟悉的 handleMessage(msg) 方法,原来回调都是在这里。
至此,整个流程大致如下:
Handler 执行发送消息的相关方法后,Message 被装进 MessageQuene 中。线程中的 Looper 则是在 loop() 方法内不断尝试从 MessageQuene 内取出 Message,然后调用与该 Message 绑定的 Handler(msg.target)对象的 dispatchMessage() 方法。最后可以看到处理消息的 handleMessage() 方法就是在 dispatchMessage() 方法内被调用的。
总结
- 在线程间通信中,子线程通过调用主线程的 Handler 的发送消息函数把子线程的 Message 发送到 MessageQuene 中。由于主线程默认调用了 Looper.loop() 方法,他会不断地去查询主线程的 MessageQuene 中是否有 Message 对象,如果有的话就把对象取出给主线程的 Handler 进行处理,从而达到了线程间通信。
- 一个线程可以有多个 Handler,但是一个线程只能对应一个 Looper 和一个 MessageQuene。