Handler 是如何跨线程的
2017-05-23 本文已影响98人
画十
Before
Lopper
是跨进程的关键类,阅读本文之前最好先熟悉Looper
,MessageQueue
为好;
先看源码
public class Handler {
final MessageQueue mQueue;
public final boolean sendMessage(Message msg) {
return sendMessageDelayed(msg, 0);
}
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) {
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);
}
public void dispatchMessage(Message msg) {
if (msg.callback != null) {
handleCallback(msg);
} else {
if (mCallback != null) {
if (mCallback.handleMessage(msg)) {
return;
}
}
handleMessage(msg);//回调到熟悉的方法啦
}
}
}
分析
- 由熟悉的
sendMessage
开始,最后都是调用enqueueMessage
方法,而最终还是调用MessageQueue
类的enqueueMessage
方法(点我),到此为止我们一般都是在新线程调用; - 接下来
Looper
类的loop
方法会在当前线程(如果是更新UI则在主线程)从MessageQueue
中获取最新消息,通过msg.target.dispatchMessage(msg);
调用到Handler
中来(上述代码),然后调用到handlemessage(msg)
我们就熟悉啦; - 由此,Handler跨线程最重要的是在当前线程(初始化
Handler
的线程)进行loop
轮询,而变量是可以在不同线程访问·的,所以Handler
可以在其他线程向MessageQueue
中插入数据,而loop
则在当前线程不断去取数据,取得数据就回调,达到跨线程的目的;