美文网首页Android技术知识Android开发经验谈Android开发
回转寿司你一定吃过!——Android消息机制(处理)

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

作者: 唐子玄 | 来源:发表于2019-02-04 16:39 被阅读2次

    这是“Android消息机制”系列的第三篇文章,系列文章目录如下:

    1. 回转寿司你一定吃过!——Android消息机制(构造)
    2. 回转寿司你一定吃过!——Android消息机制(分发)
    3. 回转寿司你一定吃过!——Android消息机制(处理)

    回转寿司的故事已经编不下去了,寿司店不会规定消费者应该如何享用寿司。但我们之所以发送消息,不就是为了想用自己的方式来处理消息吗。

    处理消息的起点


    先回忆一下分发消息的关键函数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()

    相关文章

      网友评论

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

        本文链接:https://www.haomeiwen.com/subject/isxlsqtx.html