消息机制的故事
寿司
陈放在寿司碟
上,寿司碟
按先后顺序被排成队列
送上传送带
。传送带
被启动后,寿司
挨个呈现到你面前,你有三种享用寿司的方法。
将Android概念带入后,就变成了Android消息机制的故事:
寿司碟 ---> 消息(Message)
队列 ---> 消息队列(MessageQueue)
传送带 ---> 消息泵 (Looper)
寿司 ---> 你关心的数据
享用寿司方法 ---> 处理数据方式
这一篇分析下处理消息的三种方式。
处理消息的起点
先回忆一下分发消息的关键函数Looper.loop()
,源码如下:
//省略了非关键代码 public static void loop() { ... //拿消息的无限循环 for (; ; ) { //从队头拿消息 Message msg = queue.next(); // might block ... //分发消息 msg.target.dispatchMessage(msg); ... }
还记得系列文章第一篇中留下的悬念吗?在构造消息时,为啥消息对象持有构造它的Handler对象?现在可以回答这个问题了:Looper
遍历消息时,把消息交给与其对应的Handler
处理。交接消息是通过调用Handler.dispatchMessage()
,这是消息分发的终点,也是处理消息的起点。
处理消息的方式
移步到Handler.dispatchMessage()
:
/** * Handle system messages here. */ public void dispatchMessage(Message msg) { //处理方式1 if (msg.callback != null) { handleCallback(msg); } else { //处理消息方式2 if (mCallback != null) { if (mCallback.handleMessage(msg)) { return; } } //处理消息方式3 handleMessage(msg); } }
可以清楚的看到有三种处理消息的方式
直接运行
Message
中Runnable.run()
。
public class Handler{ ... private static void handleCallback(Message message) { message.callback.run(); } ... }public final class Message implements Parcelable { ... /*package*/ Runnable callback; ... }
Message
的Runnable
是哪来的?
/** * Causes the Runnable r to be added to the message queue. * The runnable will be run on the thread to which this handler is * attached. * * @param r The Runnable that will be executed. */ public final boolean post(Runnable r) { return sendMessageDelayed(getPostMessage(r), 0); } //将 Runnable 包装成 Message private static Message getPostMessage(Runnable r) { Message m = Message.obtain(); m.callback = r; return m; }
每次调用Handler.post(Runnable r)
时,Handler
都会将Runnable
包装成Message
,这样Runnable
和Message
就可以共用消息分发逻辑,但它们的处理逻辑会有所不同,如果消息中带有Runnable
则会最优先被处理,处理方式是直接调用Runnable.run()
Handler.Callback
方式
/** * Callback interface you can use when instantiating a Handler to avoid * having to implement your own subclass of Handler. * * @param msg A {@link android.os.Message Message} object * @return True if no further handling is desired */ public interface Callback { public boolean handleMessage(Message msg); }
除了继承Handler
这种最常见的处理消息方式外,我们还可以通过Handler.Callback
来定义处理消息的方式:
/** * Constructor associates this handler with the {@link Looper} for the * current thread and takes a callback interface in which you can handle * messages. * * If this thread does not have a looper, this handler won't be able to receive messages * so an exception is thrown. * * @param callback The callback interface in which to handle messages, or null. */ public Handler(Callback callback) { this(callback, false); }
重载
handleMessage()
/** * Subclasses must implement this to receive messages. */ public void handleMessage(Message msg) { }
通常我们是通过重载这个函数来定义处理消息的方式。
总结
Android消息机制共有三种消息处理方式,它们是互斥的,优先级从高到低分别是1. Runnable.run()
2. Handler.callback
3. 重载Handler.handleMessage()
作者:唐子玄
链接:https://www.jianshu.com/p/e7d0fefcb89d
共同学习,写下你的评论
评论加载中...
作者其他优质文章