Android 中Handler 常用来做线程间通讯,另一种说法是用来切换线程,笔者认为称之通讯更为妥当,为什么这么说呢,这得从基本原理说起。
首先Handler的主要相关的对象:
ThreadLocal, Looper, MessageQueue
ThreadLocal的功能及属性可以自行了解。
MessageQueue 主要包含的两个操作,插入和读取。
其内部数据结构是一个单链表,在插入上有优势,插入和读取分别对应enqueueMessage和next 方法,
next方法源码如下:
int pendingIdleHandlerCount = -1; // -1 only during first iteration
int nextPollTimeoutMillis = 0;
for (;;) {
if (nextPollTimeoutMillis != 0) {
Binder.flushPendingCommands();
}
nativePollOnce(ptr, nextPollTimeoutMillis);
synchronized (this) {
// Try to retrieve the next message. Return if found.
final long now = SystemClock.uptimeMillis();
Message prevMsg = null;
Message msg = mMessages;
if (msg != null && msg.target == null) {
// Stalled by a barrier. Find the next asynchronous message in the queue.
do {
prevMsg = msg;
msg = msg.next;
} while (msg != null && !msg.isAsynchronous());
}
...
}
这里有两点:
- next方法为无限for循环方法
- for内部的
nativePollOnce(ptr, nextPollTimeoutMillis);
为阻塞方法,
也就是会一直阻塞等待新的消息到来,
Looper.loop()
内部也是一个for循环方法
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;
// Make sure the identity of this thread is that of the local process,
// and keep track of what that identity token actually is.
Binder.clearCallingIdentity();
final long ident = Binder.clearCallingIdentity();
// Allow overriding a threshold with a system prop. e.g.
// adb shell 'setprop log.looper.1000.main.slow 1 && stop && start'
final int thresholdOverride =
SystemProperties.getInt("log.looper."
+ Process.myUid() + "."
+ Thread.currentThread().getName()
+ ".slow", 0);
boolean slowDeliveryDetected = false;
for (;;) {
Message msg = queue.next(); // might block
if (msg == null) {
// No message indicates that the message queue is quitting.
return;
}
...
msg.target.dispatchMessage(msg);
...
}
可以注意到loop的for循环的结束条件是msg == null,也就是queue.next()返回 null 时,
这也就是looper.quit()调用时;
loop()通过msg.target.dispatchMessage(msg);
msg.target 就是handle对象,通过其内部的dispatchMessage();
完成消息分发,messageQueue的阻塞流程唤醒,进行后续业务。
到这里,也就是完成了A线程的消息,通过B线程创建的Handler传递消息,并在B线程进行业务;所以笔者理解为主动通讯,被动切换线程;
网友评论