为了账号安全,请及时绑定邮箱和手机立即绑定

回转寿司你一定吃过!——Android消息机制(处理)

标签:
Android

消息机制的故事


寿司陈放在寿司碟上,寿司碟按先后顺序被排成队列送上传送带传送带被启动后,寿司挨个呈现到你面前,你有三种享用寿司的方法。

将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);
        }
    }
  • 可以清楚的看到有三种处理消息的方式

  1. 直接运行MessageRunnable.run()

public class Handler{
     ...    private static void handleCallback(Message message) {
        message.callback.run();
    }
    ...
}public final class Message implements Parcelable {
     ...     /*package*/ Runnable callback;
    ...
}

MessageRunnable是哪来的?

    /**
     * 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,这样RunnableMessage就可以共用消息分发逻辑,但它们的处理逻辑会有所不同,如果消息中带有Runnable则会最优先被处理,处理方式是直接调用Runnable.run()

  1. 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);
    }
  1. 重载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


点击查看更多内容
TA 点赞

若觉得本文不错,就分享一下吧!

评论

作者其他优质文章

正在加载中
  • 推荐
  • 评论
  • 收藏
  • 共同学习,写下你的评论
感谢您的支持,我会继续努力的~
扫码打赏,你说多少就多少
赞赏金额会直接到老师账户
支付方式
打开微信扫一扫,即可进行扫码打赏哦
今天注册有机会得

100积分直接送

付费专栏免费学

大额优惠券免费领

立即参与 放弃机会
意见反馈 帮助中心 APP下载
官方微信

举报

0/150
提交
取消