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类位于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源码中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的调用关系就分析完毕了。