Handler的通信机制的背后的原理是,一个线程中可以定义多个 Handler 实例,但是每个 Handler 实际上引用的是同一个 Looper。当然,我们要在创建 Handler 之前先创建 Looper。而每个 Looper 又只对应一个 MessageQueue。
一、Handler的通信机制的背后的原理
Handler的通信机制的背后的原理是,一个线程中可以定义多个 Handler 实例,但是每个 Handler 实际上引用的是同一个 Looper。当然,我们要在创建 Handler 之前先创建 Looper。而每个 Looper 又只对应一个 MessageQueue。该 MessageQueue 会在创建 Looper 的时候被创建。在 MessageQueue 中使用 Message 对象来拼接一个单向的链表结构,依次来构成一个消息队列。每个 Message 是链表的一个结点,封装了我们发送的信息。
Handler 发送消息的方法分成 post 和 send 两种类型。post 的用来发送 Runnable 类型的数据,send 类型的用来发送 Message 类型的数据。但不论哪种类型最终都会调用 Handler 的 sendMessageAtTime() 方法来加入到 MessageQueue 的队列中。区别在于,post 类型的方法需要经过 Handler 的 getPostMessage() 包装成 Message 之后再发送。
当消息被添加到队列之后需要执行消息,这部分内容在 Looper 的 loop() 方法中。当我们调用 Looper 的 loop() 方法之后整个 Looper 循环就开始不断地处理消息了。当我们在循环中调用 MessageQueue 的 next() 方法来获取下一个消息的时候,会调用 nativePollOnce() 方法,该方法可能会造成线程阻塞和非阻塞,当线程为非阻塞的时候就会从 Native 层回到 Java 层,从 MessageQueuue 中取得一个消息之后给 Looper 进行处理。如果获取的时候造成线程阻塞,那么有两种情况会唤醒阻塞的线程,一个是当一个新的消息被加入到队列中,并且将会早于之前队列的所有消息被触发,那么此时将会重新设置超时时间。如果达到了超时时间同样可以从睡眠状态中返回,也就回到了 Java 层继续处理。所以,Native 层的 Looper 的作用就是通过阻塞消息队列获取消息的过程阻塞 Looper。
延伸阅读:
二、消息机制的模型有什么
Message:需要传递的消息,可以传递数据;
MessageQueue:消息队列,但是它的内部实现并不是用的队列,实际上是通过一个单链表的数据结构来维护消息列表,因为单链表在插入和删除上比较有优势。主要功能向消息池投递消息(MessageQueue.enqueueMessage)和取走消息池的消息(MessageQueue.next);
Handler:消息辅助类,主要功能向消息池发送各种消息事件(Handler.sendMessage)和处理相应消息事件(Handler.handleMessage);
Looper:不断循环执行(Looper.loop),从MessageQueue中读取消息,按分发机制将消息分发给目标处理者。