消息机制的故事
寿司陈放在寿司碟上,寿司碟按先后顺序被排成队列送上传送带。传送带被启动后,寿司挨个呈现到你面前,你有三种享用寿司的方法。
将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
共同學習,寫下你的評論
評論加載中...
作者其他優質文章