//具体实现如下,这个画张图来说明
//链表引入一个prev变量,该变量指向p也message(如果是for循环的内部第一次执行),然后把p进行向next移动,和需要插入的Message进行比较when
Message prev;
for (;😉 {
prev = p;
p = p.next;
if (p == null || when < p.when) {
break;
}
if (needWake && p.isAsynchronous()) {
needWake = false;
}
}
msg.next = p;
prev.next = msg;
}
//如果插入的是异步消息,并且消息链表第一条消息是同步屏障消息。
//或者消息链表中只有刚插入的这一个Message,并且mBlocked为true即,正在阻塞状态,收到一个消息后也进入唤醒
唤醒谁?MessageQueue.next中被阻塞的nativePollOnce
if (needWake) {
nativeWake(mPtr);
}
}
return true;
}
//android.os.MessageQueue#next
Message next() {
//native层NativeMessageQueue的指针
final long ptr = mPtr;
if (ptr == 0) {
return null;
}
…
for (;😉 {
//阻塞操作,当等待nextPollTimeoutMillis时长,或者消息队列被唤醒
//nativePollOnce用于“等待”, 直到下一条消息可用为止. 如果在此调用期间花费的时间很长, 表明对应线程没有实际工作要做,或者Native层的message有耗时的操作在执行
nativePollOnce(ptr, nextPollTimeoutMillis);
}
可以看到在MessageQueue#next会调用课程阻塞的native方法nativePollOnce
,在MessageQueue#enqueueMessage 中如果需要唤醒会调用native方法nativeWake
。
问题是怎么阻塞的,怎么唤醒的,为什么要这样设计,直接在Java层完成处理不可以吗?
带着这样的困惑,开始Native层消息机制的分析学习。
2.1 MessageQueue Init流程
图片来自:Android消息机制2-Handler(Native层)
调用Native方法初始化,返回值为native层的NativeMessageQueue指针地址
//android.os.MessageQueue#MessageQueue
MessageQueue(boolean quitAllowed) {
mQuitAllowed = quitAllowed;
//调用Native方法初始化,返回值为native层的NativeMessageQueue指针地址
mPtr = nativeInit();
}
android_os_MessageQueue_nativeInit
//java native方法 nativeInit 的jni方法,返回类型long,即 mptr
static jlong android_os_Me