从ActivityThread说起Handler相关的对象关系
Posted 小喽啰A
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了从ActivityThread说起Handler相关的对象关系相关的知识,希望对你有一定的参考价值。
在提到Handler的时候就不得不提到Looper、MessageQueue这两个对象,到底这些对象和所谓的线程是什么关系呢?它们之间是如何联系在一起的呢?又是如何做到发送消息的呢?这里就是要说明这三个问题的,如果你对这些问题也不能很好的回答出来,那就请继续往下看。
这里的思路是从ActivityThread(也就是UI线程)的Looper对象开始,讲这三个对象之间的关系。
首先看ActivityThread类的main方法:
// android.app.ActivityThread.java
public 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.java
public 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.java
public 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.java
public 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.java
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;
}
看到这里,Handler对象在创建的时候会持有当前线程Looper和MessageQueue的引用,再看sendMessage,sendMessage会最终调用到
// android.os.Handler.java
private boolean enqueueMessage(MessageQueue queue, Message msg, long uptimeMillis) {
msg.target = this;
if (mAsynchronous) {
msg.setAsynchronous(true);
}
return queue.enqueueMessage(msg, uptimeMillis);
}
当添加到消息队列后,就等待loop方法里面的训话去处理吧。。。
以上是关于从ActivityThread说起Handler相关的对象关系的主要内容,如果未能解决你的问题,请参考以下文章