Handler机制在Android系统中非常重要。由于Android系统不能在非主线程更新UI,只能在主线程中更新UI,那么当需要在非主线程更新UI时,就需要Handler机制的帮助,进行线程的切换。这也是Handler机制最平常的用法。当然利用Handler机制也可以制作一个简易的网络请求框架。
那么就从AS中一窥Handler的源码。
图如下:
从AS中看Handler的源码
首先:
Looper:Looper类中的代码不多,主要的方法如下:
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));
}
prepare()方法,可以看到从ThreadLocal中去拿Looper,如果拿不到,就将新new一个Looper,存放在ThreadLocal中,如果拿的到就抛出一个异常——一个线程中只能有一个Looper,也就要是说如果线程中已经有Looper了,就不能在调用Looper的prepare()方法了。即Looper的prepare()方法只能调用一次。同时注意ThreadLocal:线程本地变量,属于线程的私有空间,将Looper保存在ThreadLocal中,保证了Looper不会被其他线程干扰,是线程安全的,一种空间换时间的同步方式。
总结:通过prepare()方法,Looper与所在的线程绑定(放在了ThreadLocal中),保证了一个线程只能有一个Looper。
再看Looper的构造方法
private Looper(boolean quitAllowed) {
mQueue = new MessageQueue(quitAllowed);
mThread = Thread.currentThread();
}
可以看到Looper的构造方法是私有的,不能实例化,同时可以看到mQueue = new MessageQueue(quitAllowed);实例化了消息队列,也就是说Looper在prepare()后,组合了MessageQueue,一个Looper就对应一个MessageQueue,同时对应了所在线程。MessageQueue不深究,就是一队列,缓存Message的。
在看Looper的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
Printer logging = me.mLogging;
if (logging != null) {
logging.println(">>>>> Dispatching to " + msg.target + " " +
msg.callback + ": " + msg.what);
}
msg.target.dispatchMessage(msg);
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
public static @Nullable Looper myLooper() {
return sThreadLocal.get();
}
然后for (;;) 死循环,去拿MessageQueue中的Message,然后调用*msg.target.dispatchMessage(msg)*;
注意这句话,然后将message回收。loop方法完了,疑问:msg的target是谁,dispatchMessage(msg)方法做了什么?
带着疑问来看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;
}
在Handler实例化后,得到了所在线程的Looper(mLooper = Looper.myLooper();),如果Looper为null抛出异常,即没有调用Looper.prepare(),Handler不能实例化,也就是说,想要使用Handler必须在Looper的prepare()调用之后。然后得到了Looper中的MessageQueue(mQueue = mLooper.mQueue;),ok,组合关系很清楚了,继续:
使用Handler最常用的方法就是sendMessage,字面来看,推一个消息,推到哪呢?
sendMessage(Message msg),sendEmptyMessage(int what),sendMessageDelayed(msg, 0),sendMessageAtTime,post(Runnable r),postAtTime(Runnable r, long uptimeMillis),postDelayed(Runnable r, long 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);
}
private boolean enqueueMessage(MessageQueue queue, Message msg, long uptimeMillis) {
msg.target = this;
if (mAsynchronous) {
msg.setAsynchronous(true);
}
return queue.enqueueMessage(msg, uptimeMillis);
}
都是将Message推入Handler对应的Looper的MessageQueue中,注意msg.target = this这句话,之前分析Looper时,其loop()方法调用了msg.target.dispatchMessage()方法,这里就可以看到msg.target就是推送Message的Handler,在loop中调用了handler的dispatchMessage(Message msg)方法
public void dispatchMessage(Message msg) {
if (msg.callback != null) {
handleCallback(msg);
} else {
if (mCallback != null) {
if (mCallback.handleMessage(msg)) {
return;
}
}
handleMessage(msg);
}
}
我们看到如果Message的callback不为null,就执行handleCallback(msg),那么什么时候Message的callback不为null呢,看源码可知post系列方法中Message的callback不为null,send系方法中Message的callback为null,在msg.callback != null时,就执行Runnable中的run()方法。那么在msg.callback == null时,调用了handleMessage(msg),好熟悉的函数,在实例化Handler时,都会实现该方法来处理Message,看下该方法做了什么?
public void handleMessage(Message msg) {
}
一个空的方法,在实例化Handler是我们复写了handleMessage方法,具体对Message怎么处理,我们自己决定。由此一些都清楚了。
总结如下:
在使用Handler的时候,必须进行执行Looper的prepare()方法,即准备好资源,Looper与当前线程的绑定,MessageQueue的实例化,否则会抛出异常,随后Handler实例化,即取出当前线程中的Looper,拿到Looper的MessageQueue,在我们调用sendxxx或者postxxx方法时,将Message推送到Looper对应的MessageQueue中,同时将Message的target设置为本身(Handler),这是Looper调用了loop()方法,不断从MessageQueue中取出Message,调用msg.target.dispatchMessage,即Handler的dispatchMessage方法,在该方法中全都是我们自己的逻辑了,我们复写handleMessage处理传过来的Message,或者按照自己的意愿执行Runnable的run方法。至此Message就可以在不同线程间到处游蹿,最终回到Handler所在的线程,实现线程间信息的传递和交互。
从上面的总结可以看到使用Handler正确的顺序是:
Looper.prepare()–>new Handler()—>Looper.loop()
最后说明,在Activity中使用Handler时,为什么没有见到Looper.prepare()和Looper.loop(),因为在主线程中,已经默认开启了,系统已经为我们做过了这些工作。
至此Handler的分析完成。