zoukankan      html  css  js  c++  java
  • Android源码分析之Handler

      接上一篇分析,正如Android doc所说,Handler主要有2方面用处:

    1. delay执行同一线程中的某个操作,也就是schedule message、runnable在未来的某一时刻执行;

    2. 给另外一个线程发送message、runnable,让某个操作在另一个线程中执行。比如A线程只要能拿到B线程的

    handler就能通过此handler在A线程中通过post message、runnable,让这些消息的处理发生在B线程中,从而实现

    线程间的通信。AsyncTask就是通过在background线程中通过关联UI线程的handler来向UI线程发送消息的。为了看的

    更清楚些,这里摘抄下Looper.java开头处给的一个典型例子:

      * This is a typical example of the implementation of a Looper thread,
      * using the separation of {@link #prepare} and {@link #loop} to create an
      * initial Handler to communicate with the Looper.
      *
      * <pre>
      *  class LooperThread extends Thread {
      *      public Handler mHandler;
      *
      *      public void run() {
      *          Looper.prepare();
      *
      *          mHandler = new Handler() {
      *              public void handleMessage(Message msg) {
      *                  // process incoming messages here
      *              }
      *          };
      *
      *          Looper.loop();
      *      }
      *  }</pre>

    在这里,别的线程可以通过LooperThread.mHandler来实现和它的通信。

      接下来一点点分析源码,先看几个相关的:

    /**
         * 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);
        }
        
        /**
         * Subclasses must implement this to receive messages.
         */
        public void handleMessage(Message msg) {
        }
        
        /**
         * Handle system messages here.
         */
        public void dispatchMessage(Message msg) {
            if (msg.callback != null) {
                handleCallback(msg);
            } else {
                if (mCallback != null) {
                    if (mCallback.handleMessage(msg)) {
                        return;
                    }
                }
                handleMessage(msg);
            }
        }

    这个Callback接口里只有一个handleMessage方法返回boolean值,在后面Handler的ctor会用到,一般情况下都是null。这个接口的存在

    没什么特殊的含义,只是为了让你不extends Handler就能处理消息而已(正如此方法的doc所说),类似Thread和Runnable接口的关系。

    接下来是dispatchMessage方法,我们已经在上一篇分析Message的时候大概提到了。它的处理是如果message自身设置了callback,则

    直接调用callback.run()方法,否则Callback接口的作用就显现了;如果我们传递了Callback接口的实现,即mCallback非空,则调用它处理

    message,如果处理了(consumed)则直接返回,否则接着调用Handler自己的handleMessage方法,其默认实现是do nothing,如果你

    是extends Handler,那么你应该在你的子类中为handleMessage提供自己的实现。

      接下来我们首先看看Handler都有哪些关键的字段,源码如下:

    final MessageQueue mQueue;
    final Looper mLooper;
    final Callback mCallback;
    final boolean mAsynchronous;

    mQueue来自mLooper,mLooper要么是在ctor中显式指定的要么是默认当前线程的,Handler关于Message、Runnable的所有处理都delegate给了mQueue;mCallback是用户提供的Callback实现,默认是null;mAsynchronous表示Handler是否是异步的,默认是同步的。

      接下来我们来看各种各样的Handler的ctor(构造器):

    /**
         * Default constructor associates this handler with the {@link Looper} for the
         * current thread.
         *
         * If this thread does not have a looper, this handler won't be able to receive messages
         * so an exception is thrown.
         */
        public Handler() {
            this(null, false);
        }
    
        /**
         * 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);
        }
    
        /**
         * Use the provided {@link Looper} instead of the default one.
         *
         * @param looper The looper, must not be null.
         */
        public Handler(Looper looper) {
            this(looper, null, false);
        }
    
        /**
         * Use the provided {@link Looper} instead of the default one and take a callback
         * interface in which to handle messages.
         *
         * @param looper The looper, must not be null.
         * @param callback The callback interface in which to handle messages, or null.
         */
        public Handler(Looper looper, Callback callback) {
            this(looper, callback, false);
        }
    
        /**
         * Use the {@link Looper} for the current thread
         * and set whether the handler should be asynchronous.
         *
         * Handlers are synchronous by default unless this constructor is used to make
         * one that is strictly asynchronous.
         *
         * Asynchronous messages represent interrupts or events that do not require global ordering
         * with represent to synchronous messages.  Asynchronous messages are not subject to
         * the synchronization barriers introduced by {@link MessageQueue#enqueueSyncBarrier(long)}.
         *
         * @param async If true, the handler calls {@link Message#setAsynchronous(boolean)} for
         * each {@link Message} that is sent to it or {@link Runnable} that is posted to it.
         *
         * @hide
         */
        public Handler(boolean async) {
            this(null, async);
        }
    
        /**
         * Use the {@link Looper} for the current thread with the specified callback interface
         * and set whether the handler should be asynchronous.
         *
         * Handlers are synchronous by default unless this constructor is used to make
         * one that is strictly asynchronous.
         *
         * Asynchronous messages represent interrupts or events that do not require global ordering
         * with represent to synchronous messages.  Asynchronous messages are not subject to
         * the synchronization barriers introduced by {@link MessageQueue#enqueueSyncBarrier(long)}.
         *
         * @param callback The callback interface in which to handle messages, or null.
         * @param async If true, the handler calls {@link Message#setAsynchronous(boolean)} for
         * each {@link Message} that is sent to it or {@link Runnable} that is posted to it.
         *
         * @hide
         */
        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;
        }
    
        /**
         * Use the provided {@link Looper} instead of the default one and take a callback
         * interface in which to handle messages.  Also set whether the handler
         * should be asynchronous.
         *
         * Handlers are synchronous by default unless this constructor is used to make
         * one that is strictly asynchronous.
         *
         * Asynchronous messages represent interrupts or events that do not require global ordering
         * with represent to synchronous messages.  Asynchronous messages are not subject to
         * the synchronization barriers introduced by {@link MessageQueue#enqueueSyncBarrier(long)}.
         *
         * @param looper The looper, must not be null.
         * @param callback The callback interface in which to handle messages, or null.
         * @param async If true, the handler calls {@link Message#setAsynchronous(boolean)} for
         * each {@link Message} that is sent to it or {@link Runnable} that is posted to it.
         *
         * @hide
         */
        public Handler(Looper looper, Callback callback, boolean async) {
            mLooper = looper;
            mQueue = looper.mQueue;
            mCallback = callback;
            mAsynchronous = async;
        }

    我们来看3个参数的版本,即Looper,Callback,boolean,默认looper是关联的当前线程的,callback是null,async是false。当然你愿意也可以分别指定这3个值。关于ctor不需要赘述,看doc、comment就可以很容易理解。

      接下来是一堆Handler的obtainMessage函数,其实现都是直接调用Message的静态函数obtain,但相应的message的target字段都自动被设置成了当前的Handler对象。由于Message的源码已在上一篇中分析过了,这里一带而过。

      getPostMessage(Runnable r)之类的也很简单,就是将runnable包装成一个Message,其callback字段被设置成了runnable。

      接下来的一堆postxxx、sendxxx,最终会调用下面这个方法:

    private boolean enqueueMessage(MessageQueue queue, Message msg, long uptimeMillis) {
            msg.target = this;
            if (mAsynchronous) {
                msg.setAsynchronous(true);
            }
            return queue.enqueueMessage(msg, uptimeMillis);
        }

    在这里,message的target被设置成当前的Handler,如果是异步的Handler,则设置message也为异步的,然后入队,uptimeMillis表示绝对时间戳。这里需要提一下的是xxxAtFrontOfQueue方法,这个方法因为每次是将后来的message插在队列的前头,所以可能导致队列中的其他消息没机会得到处理(即饥饿),或得不到及时处理,所以说插队是不好的,慎用。正如其方法doc中所说,其实在我们的工作学习中,我也强烈推荐大家仔细看看相关类、方法的doc。我知道我们这类人都不喜欢写doc,所以既然能有doc那说明真的是必不可少的,挺重要的。

      接下来是removeCallbacks相关的,源码:

    /**
         * Remove any pending posts of Runnable r that are in the message queue.
         */
        public final void removeCallbacks(Runnable r)
        {
            mQueue.removeMessages(this, r, null);
        }
    
        /**
         * Remove any pending posts of Runnable <var>r</var> with Object
         * <var>token</var> that are in the message queue.  If <var>token</var> is null,
         * all callbacks will be removed.
         */
        public final void removeCallbacks(Runnable r, Object token)
        {
            mQueue.removeMessages(this, r, token);
        }

    其实现也都是delegate给了mQueue,有一点需要注意下就是这些方法会remove掉所有的Runnable r,而不是第一个匹配的

    (注意方法名中的s,是复数而不是单数),也就是说一次remove调用可以remove掉之前好多次post的同一个runnable,

    如果之前post的runnable还在队列中的话。

      removeMessages、hasMessages之类的方法挺简单不过多解释。

      Handler类的分析就到这了。。。(由于本人水平有限,欢迎批评指正

     
  • 相关阅读:
    泰山之行
    泰山之行
    Java EE (2) -- Java EE 6 Enterprise JavaBeans Developer Certified Expert(1z0-895)
    一、浏览器生成消息(2)
    P1194 买礼物 洛谷
    P1195 口袋的天空 洛谷
    P1546||2627 最短网络 Agri-Net 洛谷||codevs
    P3366 最小生成树【模板】 洛谷
    T2627 村村通 codevs
    【目录】我的原创技术视频教程
  • 原文地址:https://www.cnblogs.com/xiaoweiz/p/3660585.html
Copyright © 2011-2022 走看看