1、问题:handler是如何切换线程的?
想要了解这个问题,需要知道Handler、Message、MessageQuene、Looper之间的关系:
首先Message由Handler生成并放入MessageQuene中,Looper持有MessageQuene并不停的尝试从中取出Message交由Handler处理。
2、我们从代码角度看一下一个主线程发出的Message在子线程被执行的流程:
2.1 首先在创建一个HandlerThread线程,它的特点是run方法生成一个Looper
thread = new HandlerThread("handler_thread#");
();
看一下HandlerThread#run都执行了什么操作:
public void run() {
mTid = ();
();
synchronized (this) {
mLooper = ();
notifyAll();
}
(mPriority);
onLooperPrepared();
();
mTid = -1;
}
首先生成了一个Looper对象并持有这个对象的引用,然后调用()开启Looper的无限循环。
Looper#loop()
//该方法执行在调用次方法的线程中,也就是HandlerThead.
public static void loop() {
final Looper me = myLooper();
if (me == null) {
throw new RuntimeException("No Looper; () wasn't called on this thread.");
}
final MessageQueue queue = ;
//省略部分代码
for (;;) {
//不停的从MessageQueue取出message
Message msg = (); // might block
if (msg == null) {
// No message indicates that the message queue is quitting.
return;
}
//省略部分代码
try {
//一旦message不为空则交由handler处理这个消息。
(msg);
dispatchEnd = needEndTime ? () : 0;
} finally {
if (traceTag != 0) {
(traceTag);
}
}
}
}
从上面代码可以看出,Looper从MessageQuene中获取到messge之后交给message的目标handler处理这个message。因为Looper#loop()在HandlerThread线程中执行,所以handler的处理过程也是在HandlerThread线程中执行。
2.2 生成一个handler绑定HandlerThread生成的Looper对象
threadHandler = new Handler(()){
@Override
public void handleMessage(Message msg) {
(msg);
//子线程handler接收到消息,开始处理任务
collectInfo("threadHandler接收到消息开始处理");
(2000);
//告诉UI handler任务完成的消息
collectInfo("子线程处理好任务了");
}
};
在这个threadHandler对象的handleMessage()方法中处理Looper传过来的Message。由于Looper#loop()在HandlerThread线程中执行,所以handler的handleMessage处理过程也是在HandlerThread线程中执行。
2.3 我们在主线程中调用threadHanlder的发送message的方法
(1).sendToTarget();
此时发动消息是执行在主线程的,我们看下发送的代码流程:
Handler#obtainMessage
public final Message obtainMessage(int what)
{
return (this, what);
}
Message#obtain
public static Message obtain(Handler h, int what) {
Message m = obtain();
= h;
= what;
return m;
}
Message#sendToTarget
/**
* Sends this Message to the Handler specified by {@link #getTarget}.
* Throws a null pointer exception if this field has not been set.
*/
public void sendToTarget() {
(this);
}
target是Handler,此时又回到了handler#sendMessage
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, () + delayMillis);
}
public boolean sendMessageAtTime(Message msg, long uptimeMillis) {
MessageQueue queue = mQueue;
if (queue == null) {
RuntimeException e = new RuntimeException(
this + " sendMessageAtTime() called with no mQueue");
("Looper", (), e);
return false;
}
return enqueueMessage(queue, msg, uptimeMillis);
}
private boolean enqueueMessage(MessageQueue queue, Message msg, long uptimeMillis) {
= this;
if (mAsynchronous) {
(true);
}
return (msg, uptimeMillis);
}
我们继续看一下MessageQuene#enqueueMessage
boolean enqueueMessage(Message msg, long when) {
//省略部分代码
synchronized (this) {
();
= when;
Message p = mMessages;
boolean needWake;
if (p == null || when == 0 || when < ) {
// New head, wake up the event queue if blocked.
= p;
mMessages = msg;
needWake = mBlocked;
} else {
// Inserted within the middle of the queue. Usually we don't have to wake
// up the event queue unless there is a barrier at the head of the queue
// and the message is the earliest asynchronous message in the queue.
needWake = mBlocked && == null && ();
Message prev;
for (;;) {
prev = p;
p = ;
if (p == null || when < ) {
break;
}
if (needWake && ()) {
needWake = false;
}
}
= p; // invariant: p ==
= msg;
}
//省略部分代码
}
return true;
}
从代码可以看出,此方法就是把消息按照时间顺序放入MessageQuene中(此时是在主线程执行)等待被()的无限循环获取方法取出并传给handler处理(此时是在HandlerThread线程中执行)。至此消息在主线程生成在HandlerThread线程被执行的过程就完成了。
完整的演示demo代码地址:/zhaohe9981/