Android源码-Handler分析

Handler简介

Handler是Android消息机制的上层接口,多数开发者会使用Handler去更新UI或做延时处理。如下代码所示:

new Thread(new Runnable() {
       @Override
       public void run() {
           // do something
           handler.sendMessage(message)
       }
   }).start();
new Handler().postDelayed(new Runnable() {
        @Override
        public void run() {
            //do something
        }
    }, 2000);

Handler分析

Handler类位于android.os包下,继承Object类

其中可见的构造方法有三个

/**
 * 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);
}

其中Callback是Handler内部定义的接口,只有一个回调方法handleMessage

/**
   * 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);
  }

这里先来分析无参构造方法

public Handler() {
    this(null, false);
}

在无参构造方法中调用了重载方法,如下,省略部分代码:


/**
     * 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 respect 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) {
        ....//省略
        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;
    }

这里需要注意下@hide修饰为隐藏方法,不能直接调用,可以通过反射调用。

这里需要一个Looper对象,如果mLooper属性为空,会抛出异常。如果在主线程(UI线程)中创建Handler对象,默认在主线程中已经调用了Looper.prepareMainLooper()方法,详细代码在ActivityThread类中main方法中。Looper.myLooper()方法会获取当前线程的Looper对象,当当前线程中没有Looper对象时,创建Handler会抛出异常,这就是常见于在子线程中创建Handler之前没有调用Looper.prepare()方法出现的崩溃,有问题代码如下:

new Thread(new Runnable() {
          @Override
          public void run() {
              Handler mHandler = new Handler();
          }
      }).start();

正确在子线程中创建Handler如下:

new Thread(new Runnable() {
         @Override
         public void run() {
             Looper.prepare();
             Handler mHandler = new Handler();
             Looper.loop();
         }
     }).start();

这里需要注意的是在创建完Handler后,这里又调用了Looper.loop()方法,这个方法是为了在这个线程中运行消息队列。

Looper分析

我们可以查看Looper源码中prepare方法可知,如下:

    public static void prepare() {
        prepare(true);
    }

    private static void prepare(boolean quitAllowed) {
        if (sThreadLocal.get() != null) {
            throw new RuntimeException("Only one Looper may be created per thread");
        }
        sThreadLocal.set(new Looper(quitAllowed));
    }

当我们调用Looper.prepare方法时,调用重载方法,为当前线程关联一个新的Looper对象,这里使用的是ThreadLocal,有兴趣的可以查看下源码。我们接着看Looper.loop方法:

   /**
     * Run the message queue in this thread. Be sure to call
     * {@link #quit()} to end the loop.
     */
    public static void loop() {
        final Looper me = myLooper();
        if (me == null) {
            throw new RuntimeException("No Looper; Looper.prepare() wasn't called on this thread.");
        }
        final MessageQueue queue = me.mQueue;

        // Make sure the identity of this thread is that of the local process,
        // and keep track of what that identity token actually is.
        Binder.clearCallingIdentity();
        final long ident = Binder.clearCallingIdentity();

        for (;;) {
            Message msg = queue.next(); // might block
            if (msg == null) {
                // No message indicates that the message queue is quitting.
                return;
            }

            // This must be in a local variable, in case a UI event sets the logger
            final Printer logging = me.mLogging;
            if (logging != null) {
                logging.println(">>>>> Dispatching to " + msg.target + " " +
                        msg.callback + ": " + msg.what);
            }

            final long slowDispatchThresholdMs = me.mSlowDispatchThresholdMs;

            final long traceTag = me.mTraceTag;
            if (traceTag != 0 && Trace.isTagEnabled(traceTag)) {
                Trace.traceBegin(traceTag, msg.target.getTraceName(msg));
            }
            final long start = (slowDispatchThresholdMs == 0) ? 0 : SystemClock.uptimeMillis();
            final long end;
            try {
                msg.target.dispatchMessage(msg);
                end = (slowDispatchThresholdMs == 0) ? 0 : SystemClock.uptimeMillis();
            } finally {
                if (traceTag != 0) {
                    Trace.traceEnd(traceTag);
                }
            }
            if (slowDispatchThresholdMs > 0) {
                final long time = end - start;
                if (time > slowDispatchThresholdMs) {
                    Slog.w(TAG, "Dispatch took " + time + "ms on "
                            + Thread.currentThread().getName() + ", h=" +
                            msg.target + " cb=" + msg.callback + " msg=" + msg.what);
                }
            }

            if (logging != null) {
                logging.println("<<<<< Finished to " + msg.target + " " + msg.callback);
            }

            // Make sure that during the course of dispatching the
            // identity of the thread wasn't corrupted.
            final long newIdent = Binder.clearCallingIdentity();
            if (ident != newIdent) {
                Log.wtf(TAG, "Thread identity changed from 0x"
                        + Long.toHexString(ident) + " to 0x"
                        + Long.toHexString(newIdent) + " while dispatching to "
                        + msg.target.getClass().getName() + " "
                        + msg.callback + " what=" + msg.what);
            }

            msg.recycleUnchecked();
        }
    }

这里主要逻辑是获取当前Looper对象的MessageQueue队列,for死循环不断的从队列中取出消息,调用msg.target.dispatchMessage(msg);这个的target就是Handler对象,这个target是在Handler中sendMessage系列方法中设置引用的,代码如下:

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

msg.target = this,到这里对Handler的调用关系就分析完毕了,有兴趣的可以查看源码,谢谢。

猜你喜欢

转载自blog.csdn.net/zhe_ge_sha_shou/article/details/80710648