zoukankan      html  css  js  c++  java
  • 【原创】源码角度分析Android的消息机制系列(六)——Handler的工作原理

    ι 版权声明:本文为博主原创文章,未经博主允许不得转载。

    先看Handler的定义:

    /**
     * A Handler allows you to send and process {@link Message} and Runnable
     * objects associated with a thread's {@link MessageQueue}.  Each Handler
     * instance is associated with a single thread and that thread's message
     * queue.  When you create a new Handler, it is bound to the thread /
     * message queue of the thread that is creating it -- from that point on,
     * it will deliver messages and runnables to that message queue and execute
     * them as they come out of the message queue.
     * 
     * <p>There are two main uses for a Handler: (1) to schedule messages and
     * runnables to be executed as some point in the future; and (2) to enqueue
     * an action to be performed on a different thread than your own.
     * ……….
     * */
    public class Handler {
    ……..
    }

    由源码中对Handler的定义以及注释,我们可知,Handler主要就是用来发送和处理消息的。每一个Handler的实例都和一个线程以及该线程的MessageQueue相关联。Hadnler主要有2个作用:①在未来某个时刻去发送或处理Message或Runnable(post方法)②在另一个线程中去处理消息(send方法)。

    再看Handler的构造方法:

    public Handler() {
            this(null, false);
        }
    …….
    public Handler(Callback callback, boolean async) {
            if (FIND_POTENTIAL_LEAKS) {
                final Class<? extends Handler> klass = getClass();
                if ((klass.isAnonymousClass() || klass.isMemberClass() || klass.isLocalClass()) &&
                        (klass.getModifiers() & Modifier.STATIC) == 0) {
                    Log.w(TAG, "The following Handler class should be static or leaks might occur: " +
                        klass.getCanonicalName());
                }
            }
     
            mLooper = Looper.myLooper();
            if (mLooper == null) {
                throw new RuntimeException(
                    "Can't create handler inside thread that has not called Looper.prepare()");
            }
            mQueue = mLooper.mQueue;
            mCallback = callback;
            mAsynchronous = async;
        }
     ……

    由构造方法可知,当前线程中没有Looper时,若创建Handler对象,则会抛出"Can't create handler inside thread that has not called Looper.prepare()"异常。所以,必须要在有Looper的线程中创建Handler,否则,程序将抛出异常。

    Handler的工作主要包含消息的发送和接收过程。消息的发送可以通过post的一系列方法以及send的一系列方法来实现。下面来看一系列post方法:

       public final boolean post(Runnable r)
        {
           return  sendMessageDelayed(getPostMessage(r), 0);
        }
        public final boolean postAtTime(Runnable r, long uptimeMillis)
        {
            return sendMessageAtTime(getPostMessage(r), uptimeMillis);
        }
        public final boolean postAtTime(Runnable r, Object token, long uptimeMillis)
        {
            return sendMessageAtTime(getPostMessage(r, token), uptimeMillis);
        }
        public final boolean postDelayed(Runnable r, long delayMillis)
        {
            return sendMessageDelayed(getPostMessage(r), delayMillis);
        }
        public final boolean postAtFrontOfQueue(Runnable r)
        {
            return sendMessageAtFrontOfQueue(getPostMessage(r));
        }

    通过源码,我们可以知道,post的一系列方法最终还是通过send的一系列方法来实现的。

    下面看send的一系列发送消息的源码:

        public final boolean sendMessage(Message msg)
        {
            return sendMessageDelayed(msg, 0);
        }
        public final boolean sendEmptyMessage(int what)
        {
            return sendEmptyMessageDelayed(what, 0);
        }
        public final boolean sendMessageDelayed(Message msg, long delayMillis)
        {
            if (delayMillis < 0) {
                delayMillis = 0;
            }
            return sendMessageAtTime(msg, SystemClock.uptimeMillis() + delayMillis);
        }
        public boolean sendMessageAtTime(Message msg, long uptimeMillis) {
            MessageQueue queue = mQueue;
            if (queue == null) {
                RuntimeException e = new RuntimeException(
                        this + " sendMessageAtTime() called with no mQueue");
                Log.w("Looper", e.getMessage(), e);
                return false;
            }
            return enqueueMessage(queue, msg, uptimeMillis);
        }

    由源码可知,Handler发送消息的过程,其实就是向消息队列中插入了一条消息。

    由MessageQueue的工作原理和Looper的工作原理我们可以知道,当MessageQueue中插入了新的消息后,next方法就会返回该消息给Looper,Looper接收到消息并开始处理消息,但最终Looper是通过调用Handler的dispatchMessage方法来处理消息的,即消息最终还是交给了Handler去处理。

    下面来看Handler的dispatchMessage方法的源码,如下:

     public void dispatchMessage(Message msg) {
            if (msg.callback != null) {
                handleCallback(msg);
            } else {
                if (mCallback != null) {
                    if (mCallback.handleMessage(msg)) {
                        return;
                    }
                }
                handleMessage(msg);
            }
        }
        private static void handleCallback(Message message) {
            message.callback.run();
        }

    首先,判断了Message的callback是否为null,若不为null,则调用handleCallback方法。

    Message中有属性:  /*package*/ Runnable callback;  那么,message.callback即Handler的post方法所传递的Runnable参数。再结合handleCallback方法的源码可知,handleCallback方法其实就是开启了一个子线程,去处理post方法。

    再看dispatchMessage方法的源码,若Message的callback为空,则判断mCallback是否为null,由Handler的源码:

    final Callback mCallback;
        public interface Callback {
            public boolean handleMessage(Message msg);
        }
        /**
         * Subclasses must implement this to receive messages.
         */
        public void handleMessage(Message msg) {
        }

    可知,Callback就是一个接口,而且其中定义了handleMessage方法。由此我们可以联想到,当需要获取一个Handler实例时,我们除了可以继承Handler,重写handleMessage方法外,我们还可以通过实现Callback 接口,然后实现接口中的handleMessage方法来实现。

    接着来看dispatchMessage方法的源码,若mCallback为null,最后还是调用handleMessage方法来处理消息。

    在开发过程中,当用Handler处理消息时,我们一般是需要重写handleMessage方法的,处理消息的逻辑由我们自己来写。

     

  • 相关阅读:
    [转]Android自定义控件三部曲系列完全解析(动画, 绘图, 自定义View)
    【深入Java虚拟机】之二:Java垃圾回收机制
    【深入Java虚拟机】之一:Java内存模型
    java线程安全
    [转]软键盘用法总结
    jqgrid 不能选中行, 每次点击单元格都自动选中第一行
    TextBox禁用与启用的方法
    Easyui TextBox 添加事件的方法
    运行程序时抛出异常“找不到请求的 .Net Framework Data Provider。可能没有安装。”
    序列 Sequence
  • 原文地址:https://www.cnblogs.com/mengyi/p/7103216.html
Copyright © 2011-2022 走看看