Android源码分析之Handler

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

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

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

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

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

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

  * 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来实现和它的通讯。函数

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

/**
     * 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。这个接口的存在post

没什么特殊的含义,只是为了让你不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类的分析就到这了。。。(因为本人水平有限,欢迎批评指正

相关文章
相关标签/搜索