上文介绍了 Handler 的创建,今天看下消息的传递机制
首先发送一个消息,Handler 的 sendMessage 和 post
public final boolean post(Runnable r)
{
return sendMessageDelayed(getPostMessage(r), 0);
}
public final boolean sendMessage(Message msg)
{
return sendMessageDelayed(msg, 0);
}
private static Message getPostMessage(Runnable r) {
Message m = Message.obtain();
m.callback = r;
return m;
}
这两函数同样会走到 enqueueMessage 方法中,注意这里的 getPostMessage 方法将 Runnable 设置为 Message 的 callback 。
private boolean enqueueMessage(MessageQueue queue, Message msg, long uptimeMillis) {
msg.target = this;
if (mAsynchronous) {
msg.setAsynchronous(true);
}
return queue.enqueueMessage(msg, uptimeMillis);
}
注意这里将 Message 的 target 属性设置为当前 Handler 了。看下 MessageQueue 的 enqueueMessage 方法
Message mMessages;
boolean enqueueMessage(Message msg, long when) {
//
synchronized (this) {
//
//将消息置为使用中
msg.markInUse();
msg.when = when;
Message p = mMessages;
//等待判断
boolean needWake;
//
if (needWake) {
nativeWake(mPtr);
}
}
return true;
}
判断消息的参数是否符合,判断消息插入的位置(后文讲解),之后调用 nativeWake 将消息插入到 MessageQueue 中。nativeWake 是 native 方法,在 native 的 MessageQueue,上文给到地址了。
static void android_os_MessageQueue_nativeWake(JNIEnv* env, jclass clazz, jlong ptr) {
NativeMessageQueue* nativeMessageQueue = reinterpret_cast<NativeMessageQueue*>(ptr);
nativeMessageQueue->wake();
}
void NativeMessageQueue::wake() {
mLooper->wake();
}
nativeMessageQueue 有调用 native 的 looper 的 wake()
void Looper::wake() {
uint64_t inc = 1;
ssize_t nWrite = TEMP_FAILURE_RETRY(write(mWakeEventFd, &inc, sizeof(uint64_t)));
if (nWrite != sizeof(uint64_t)) {
if (errno != EAGAIN) {
LOG_ALWAYS_FATAL("Could not write wake signal to fd %d: %s",
mWakeEventFd, strerror(errno));
}
}
}
上文已说明,在创建的 mWakeEventFd 中写数据。
Android 线程间消息的发送已经明白,接下来看下怎么取出数据并分发。
public static void loop() {
final Looper me = myLooper();
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;
}
try {
msg.target.dispatchMessage(msg);
end = (slowDispatchThresholdMs == 0) ? 0 : SystemClock.uptimeMillis();
} finally {
if (traceTag != 0) {
Trace.traceEnd(traceTag);
}
}
msg.recycleUnchecked();
}
}
获取 Looper 对象,由 Looper 获取 MessageQueue 对象,在 MessageQueue 中调用 next() 取出 message,之后分发 message。
msg.target 就是当前的 Handler,所以 msg.target.dispatchMessage(msg); 实则调用了发送 Handler 的 dispatchMessage。
public void dispatchMessage(Message msg) {
if (msg.callback != null) {
handleCallback(msg);
} else {
if (mCallback != null) {
if (mCallback.handleMessage(msg)) {
return;
}
}
handleMessage(msg);
}
}
先判断 callback 是否为 null,也就是是否是 post 方式发送的消息。如果不为 null 的话,直接运行 Runnable。
private static void handleCallback(Message message) {
message.callback.run();
}
在判断 mCallback 是否为 null,不为 null,则会执行 mCallback的handleMessage 方法。比如插件化技术中,去 Hook 类 H,重写 handlerMessage 方法,当收到的消息类型为 LAUNCH_ACTIVITY 时,处理相关逻辑。
之后处理自身的 handleMessage
public void handleMessage(Message msg) {
}
接下来重点了解下 next()
Message next() {
//
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) {
if (now < msg.when) {
//时间未到
} else {
mBlocked = false;
if (prevMsg != null) {
prevMsg.next = msg.next;
} else {
mMessages = msg.next;
}
msg.next = null;
//
msg.markInUse();
return msg;
}
} else {
// No more messages.
nextPollTimeoutMillis = -1;
}
//其他处理
}
}
}
nativePollOnce 一直阻塞,当有消息或超时时,就会返回。判断消息类型、消息触发时间,之后返回此消息。
nativePollOnce() 函数时 native 层,
static void android_os_MessageQueue_nativePollOnce(JNIEnv* env, jobject obj,
jlong ptr, jint timeoutMillis) {
NativeMessageQueue* nativeMessageQueue = reinterpret_cast<NativeMessageQueue*>(ptr);
nativeMessageQueue->pollOnce(env, obj, timeoutMillis);
}
void NativeMessageQueue::pollOnce(JNIEnv* env, jobject pollObj, int timeoutMillis) {
mPollEnv = env;
mPollObj = pollObj;
mLooper->pollOnce(timeoutMillis);
mPollObj = NULL;
mPollEnv = NULL;
if (mExceptionObj) {
env->Throw(mExceptionObj);
env->DeleteLocalRef(mExceptionObj);
mExceptionObj = NULL;
}
}
转发给 nativeMessageQueue 的 pollOnce,之后有转发给 mLooper 的 pollOnce。我们上节提到了 pollOnce,它会转发给 pollInner,这里代码就不全贴了,重点看下 epoll_wait 函数。
int eventCount = epoll_wait(mEpollFd, eventItems, EPOLL_MAX_EVENTS, timeoutMillis);
epoll_wait 这个系统调用是用来等待 mEpollFd 中的事件。eventItems 指向调用者可以使用的事件的内存区域。EPOLL_MAX_EVENTS 告知内核有多少个 events,必须要大于 0。timeoutMillis 这个参数是用来制定 epoll_wait 会阻塞多少毫秒。这个函数会阻塞调用线程,当一个文件描述符触发了事件,或者 timeout 超时了就会返回。