在提到Handler的时候就不得不提到Looper、MessageQueue这两个对象,到底这些对象和所谓的线程是什么关系呢?它们之间是如何联系在一起的呢?又是如何做到发送消息的呢?这里就是要说明这三个问题的,如果你对这些问题也不能很好的回答出来,那就请继续往下看。
这里的思路是从ActivityThread(也就是UI线程)的Looper对象开始,讲这三个对象之间的关系。 首先看ActivityThread类的main方法:
// android.app.ActivityThread.javapublic static void main(String[] args) { ... // 前面省略若干 Looper.PRepareMainLooper(); ActivityThread thread = new ActivityThread(); thread.attach(false); ... // 中间省略若干 Looper.loop(); throw new RuntimeException("Main thread loop unexpectedly exited");}这里在main方法中首先调用了Looper.prepareMainLooper()方法,然后在main方法的结尾调用了Looper.loop();这里我们先来看看Looper.prepareMainLooper()做了哪些操作。
// android.os.Looper.javapublic static void prepareMainLooper() { prepare(false); synchronized (Looper.class) { if (sMainLooper != null) { throw new IllegalStateException("The main Looper has already been prepared."); } sMainLooper = myLooper(); }}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方法其实就是创建了一个Looper对象,然后绑定到了ThreadLocal对象上,而ThreadLocal对象又是线程绑定的,因此,Looper对象也被绑定到了UI线程上面。然后继续看Looper对构造方法:
// android.os.Looper.java private Looper(boolean quitAllowed) { mQueue = new MessageQueue(quitAllowed); mThread = Thread.currentThread();}可以看到在Looper的构造方法中创建了一个MessageQueue对象,至此,Looper、MessageQueue对象是如何关联的已经很清楚了。总结一下,Thread会有一个ThreadLocal对象,ThreadLocal又持有一个Looper对象,Looper又持有一个MessageQueue对象。就是这样。。。至少没有我之前想象的复杂。 然而,Handler和它们是如何联系起来的呢?这个问题我们还是先不去说,先来看Looper是如何处理消息的,这里来看Looper.loop()方法:
// android.os.Looper.javapublic static void loop() { final Looper me = myLooper(); final MessageQueue queue = me.mQueue; for (;;) { Message msg = queue.next(); // might block if (msg == null) { return; } try { msg.target.dispatchMessage(msg); } finally { msg.recycleUnchecked(); } }这里省略很多无关的代码,可以看到,当执行到Looper.loop()方法的时候,这里会进入一个死循环,MessageQueue.next()方法是阻塞式的,所以当有消息的时候就会立即处理,没有消息的时候就会一直等待。 处理消息最终会调用到Message.target.dispatchMessage()方法,这里的target其实是一个Handler对象,所以最终处理消息是交给了Handler.diapatchMessage()方法去处理。
// android.os.Handler.javapublic void dispatchMessage(Message msg) { if (msg.callback != null) { handleCallback(msg); } else { if (mCallback != null) { if (mCallback.handleMessage(msg)) { return; } } handleMessage(msg); }}private static void handleCallback(Message message) { message.callback.run();}这里的msg.callback其实是一个Runnable对象,如果存在的话,会直接调用它的run()方法。Handler.post()、Handler.postDelay()会最终调用到这里。 另外两个调用也很明显,如果Handler设置了CallBack对象,则会首先调用callback对象的handleMessage方法,如果该方法没有消费掉(就是没有返回true)Message对象,才会调用到Handler.handleMessage()方法。 说到这里,才开始说起Handler对象,通俗的讲,Handler对象只是封装了消息的发送和接收相关的方法。这里从创建Handler对象开始。当用户从一个线程开始创建Handler对象的时候,会最终调用到这个构造方法:
// android.os.Handler.javapublic 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;}看到这里,Handler对象在创建的时候会持有当前线程Looper和MessageQueue的引用,再看sendMessage,sendMessage会最终调用到
// android.os.Handler.javaprivate boolean enqueueMessage(MessageQueue queue, Message msg, long uptimeMillis) { msg.target = this; if (mAsynchronous) { msg.setAsynchronous(true); } return queue.enqueueMessage(msg, uptimeMillis);}当添加到消息队列后,就等待loop方法里面的训话去处理吧。。。
新闻热点
疑难解答