接触Android一定对Handler不陌生,它是用来处理线程间通信问题。例如如下代码:
public class HandlerTestActivity extends Activity {
Handler mHandler = new Handler() {
@Override
public void handleMessage(Message msg) {
// 在主线程处理这个消息
}
};
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
new Thread(new Runnable() {
@Override
public void run() {
mHandler.sendEmptyMessage(1);
}
}).start();
}
}
那么问题来了,明明是在子线程中发出的消息给Handler,但是为什么最终会在主线程中处理呢?下面来分析下。
分析之前,必须要知道Handler与Looper、MessageQueue和Message的关系,请度娘看看相关资料。
了解以上的关系之后,我们就可以开始探讨上面那个问题:
1、如果我们需要在子线程创建一个Handler时,我们需要这么做:
Looper.prepare();
Handler handler = new Handler();
Looper.loop();
这是首先为当前线程创建一个消息循环Looper给Handler使用,Looper.loop()进行循环获取消息。
延伸:为什么在主线程创建Handler不需要调用Looper.prepare()和Looper.loop()呢?
这是因为系统在启动程序的时候,已经在ActivityThread进行了上面的操作,这是源码:
public static void main(String[] args) {
SamplingProfilerIntegration.start();
// CloseGuard defaults to true and can be quite spammy. We
// disable it here, but selectively enable it later (via
// StrictMode) on debug builds, but using DropBox, not logs.
CloseGuard.setEnabled(false);
Process.setArgV0("<pre-initialized>");
Looper.prepareMainLooper();
if (sMainThreadHandler == null) {
sMainThreadHandler = new Handler();
}
ActivityThread thread = new ActivityThread();
thread.attach(false);
if (false) {
Looper.myLooper().setMessageLogging(new
LogPrinter(Log.DEBUG, "ActivityThread"));
}
Looper.loop();
throw new RuntimeException("Main thread loop unexpectedly exited");
}
2、我们使用Handler发送消息时,无论在哪个线程发送,最终会把消息保存在消息队列里,也就是保存到MessageQueue里,请看源码:
public class Handler {
/**
* Handle system messages here.
*/
public void dispatchMessage(Message msg) {
if (msg.callback != null) {
handleCallback(msg);
} else {
if (mCallback != null) {
if (mCallback.handleMessage(msg)) {
return;
}
}
handleMessage(msg);
}
}
public final boolean sendMessage(Message msg)
{
return sendMessageDelayed(msg, 0);
}
public final boolean sendEmptyMessage(int what)
{
return sendEmptyMessageDelayed(what, 0);
}
public final boolean sendEmptyMessageDelayed(int what, long delayMillis) {
Message msg = Message.obtain();
msg.what = what;
return sendMessageDelayed(msg, delayMillis);
}
public final boolean sendEmptyMessageAtTime(int what, long uptimeMillis) {
Message msg = Message.obtain();
msg.what = what;
return sendMessageAtTime(msg, uptimeMillis);
}
public final boolean sendMessageDelayed(Message msg, long delayMillis)
{
if (delayMillis < 0) {
delayMillis = 0;
}
return sendMessageAtTime(msg, SystemClock.uptimeMillis() + 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); // 将消息保存到MessageQueue queue里面
}
}
消息保存到MessageQueue之后,谁来取消息把它给Handler处理呢?没错,就是Looper,请看源码:
public final class Looper {
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;
...
for (;;) {
Message msg = queue.next(); // might block
if (msg == null) {
// No message indicates that the message queue is quitting.
return;
}
...
msg.target.dispatchMessage(msg); // msg.target也就是执行这个消息的Handler
...
}
}
}
所以,整个流程就是这样的:
1、在任意地方通过Handler给自己发送消息Message,并把Message排好队保存在MessageQueue里;
2、Handler所处线程的那个Looper进行循环到MessageQueue里取消息,并把消息按时传到Handler执行。
就这么两步!
所以究竟消息是在哪个线程被Handler处理呢?答案是Looper进行循环的那个线程,也就是创建Handler那个线程。因为是在Looper.loop调用Handler去执行消息的,Looper在哪个线程调用,消息就在哪个线程被Handler处理:
<pre name="code" class="java">msg.target.dispatchMessage(msg); // msg.target也就是执行这个消息的Handler
因为对应Looper所在线程与创建对应Handler的线程必须是同一条,所以无论从哪个线程发送消息给Handler,最终会在创建Handler那个线程执行这个消息。