消息都是存放在一个消息队列中去,而消息循环线程就是围绕这个消息队列进入一个无限循环的,直到线程退出。如果队列中有消息,消息循环线程就会把它取出来,并分发给相应的Handler进行处理;如果队列中没有消息,消息循环线程就会进入空闲等待状态,等待下一个消息的到来。在编写Android应用程序时,当程序执行的任务比较繁重时,为了不阻塞UI主线程而导致ANR的发生,我们通常的做法的创建一个子线程来完成特定的任务。在创建子线程时,有两种选择,一种通过创建Thread对象来创建一个无消息循环的子线程;还有一种就是创建一个带有消息循环的子线程,而创建带有消息循环的子线程由于两种实现方法,一种是直接利用Android给我们封装好的HandlerThread类来直接生成一个带有消息循环的线程对象,另一种方法是在实现线程的run()方法内使用以下方式启动一个消息循环:
@Override
public void run() {
// TODO Auto-generated method stub
Looper.prepare();
...
Looper.loop();
}
关于消息循环的创建及启动过程在稍后进行分析。当启动了一个带消息循环的子线程时,就可以往这个子线程中发送消息,那么消息是如何发送到子线程的消息队列中的呢?这就需要使用Handler对象来完成这一艰巨的任务。
Hanlder对象的构造过程
Handler对象的构造方法有三种:
1. 使用当前线程的Looper来构造Handler对象,如果当前线程没有消息循环,则当前Handler不能处理消息
public Handler() {
if (FIND_POTENTIAL_LEAKS) {
final Class<? extends Handler> klass = getClass();
if ((klass.isAnonymousClass() || klass.isMemberClass() || klass.isLocalClass()) &&
(klass.getModifiers() & Modifier.STATIC) == 0) {
Log.w(TAG, "The following Handler class should be static or leaks might occur: " +
klass.getCanonicalName());
}
}
//使用当前线程的Looper
mLooper = Looper.myLooper();
if (mLooper == null) {
throw new RuntimeException(
"Can't create handler inside thread that has not called Looper.prepare()");
}
//使用当前线程的消息队列
mQueue = mLooper.mQueue;
mCallback = null;
}
获取当前线程的Looper对象过程:
public static Looper myLooper() {
//从线程本地存储对象中取出当前线程的Looper对象
return sThreadLocal.get();
}
2. 使用指定的Looper对象来构造Handler对象
public Handler(Looper looper) {
mLooper = looper;
mQueue = looper.mQueue;
mCallback = null;
}
这种构造方法就是利用已有的Looper对象来构造对应的Handler对象,因此在构造Handler对象之前必须首先构造一个Looper对象。
frameworks\base\core\java\android\os\Looper.java
public static void prepare() {
prepare(true);
}
使用另一个prepare方法来构造Looper对象,参数true表示该消息循环可以退出
private static void prepare(boolean quitAllowed) {
//首先从线程本地存储中查找是否已经存在对应的Looper对象了,
if (sThreadLocal.get() != null) {
throw new RuntimeException("Only one Looper may be created per thread");
}
//创建一个新的Looper对象,并保存到线程存储对象中
sThreadLocal.set(new Looper(quitAllowed));
}
该函数调用了Looper的构造函数来构造一个Looper对象
private Looper(boolean quitAllowed) {
mQueue = new MessageQueue(quitAllowed);
mRun = true;
mThread = Thread.currentThread();
}
在构造Looper对象时,自动创建一个Java层的消息循环队列MessageQueue对象。消息队列构造过程:
MessageQueue(boolean quitAllowed) {
mQuitAllowed = quitAllowed;
nativeInit();
}
在构造Java层的消息队列MessageQueue对象时,会通过JNI进入C++层,在C++层构造一个与Java层消息队列相对应的消息队列对象
frameworks\base\core\jni\android_os_MessageQueue.cpp
static void android_os_MessageQueue_nativeInit(JNIEnv* env, jobject obj) {
//在C++层创建NativeMessageQueue对象
NativeMessageQueue* nativeMessageQueue = new NativeMessageQueue();
if (!nativeMessageQueue) {
jniThrowRuntimeException(env, "Unable to allocate native queue");
return;
}
nativeMessageQueue->incStrong(env);
//将C++的NativeMessageQueue对象指针保存到Java的MessageQueue对象成员变量mPtr中
android_os_MessageQueue_setNativeMessageQueue(env, obj, nativeMessageQueue);
}
在C++层创建了一个NativeMessageQueue对象,NativeMessageQueue的构造过程如下:
NativeMessageQueue::NativeMessageQueue() : mInCallback(false), mExceptionObj(NULL) {
mLooper = Looper::getForThread();
if (mLooper == NULL) {
mLooper = new Looper(false);
Looper::setForThread(mLooper);
}
}
这里又创建了一个C++的Looper对象,下图描述了这些对象之间的关系:
C++层的Looper对象构造过程:
Looper::Looper(bool allowNonCallbacks) :
mAllowNonCallbacks(allowNonCallbacks), mSendingMessage(false),
mResponseIndex(0), mNextMessageUptime(LLONG_MAX) {
int wakeFds[2];
//通过pipe系统调用来创建了一个管道了
int result = pipe(wakeFds);
LOG_ALWAYS_FATAL_IF(result != 0, "Could not create wake pipe. errno=%d", errno);
mWakeReadPipeFd = wakeFds[0];
mWakeWritePipeFd = wakeFds[1];
result = fcntl(mWakeReadPipeFd, F_SETFL, O_NONBLOCK);
LOG_ALWAYS_FATAL_IF(result != 0, "Could not make wake read pipe non-blocking. errno=%d",errno);
result = fcntl(mWakeWritePipeFd, F_SETFL, O_NONBLOCK);
LOG_ALWAYS_FATAL_IF(result != 0, "Could not make wake write pipe non-blocking. errno=%d",errno);
// 通过epoll_create来创建一个epoll专用的文件描述符
mEpollFd = epoll_create(EPOLL_SIZE_HINT);
LOG_ALWAYS_FATAL_IF(mEpollFd < 0, "Could not create epoll instance. errno=%d", errno);
struct epoll_event eventItem;
memset(& eventItem, 0, sizeof(epoll_event)); // zero out unused members of data field union
eventItem.events = EPOLLIN;
eventItem.data.fd = mWakeReadPipeFd;
//通过epoll_ctl函数来告诉epoll要监控相应的文件描述符
result = epoll_ctl(mEpollFd, EPOLL_CTL_ADD, mWakeReadPipeFd, & eventItem);
LOG_ALWAYS_FATAL_IF(result != 0, "Could not add wake read pipe to epoll instance. errno=%d",errno);
}
构造Looper对象时,创建了无名管道,并创建了epoll实例,同时将管道的读端添加到epoll中监听。这里就是告诉mEpollFd,它要监控mWakeReadPipeFd文件描述符的EPOLLIN事件,即当管道中有内容可读时,就唤醒当前正在等待管道中的内容的线程。管道就是一个文件,在管道的两端,分别是两个打开文件文件描述符,这两个打开文件描述符都是对应同一个文件,其中一个是用来读的,别一个是用来写的,一般的使用方式就是,一个线程通过读文件描述符中来读管道的内容,当管道没有内容时,这个线程就会进入睡眠等待状态,而另外一个线程通过写文件描述符来向管道中写入内容,写入内容的时候,如果另一端正有线程正在等待管道中的内容,那么这个线程就会被唤醒。这个等待和唤醒的操作就是借助Linux系统中的epoll机制。 Linux系统中的epoll机制为处理大批量句柄而作了改进的poll,是Linux下多路复用IO接口select/poll的增强版本。
3. 使用指定的消息处理Callback对象来构造Hander对象
public Handler(Callback callback) {
if (FIND_POTENTIAL_LEAKS) {
final Class<? extends Handler> klass = getClass();
if ((klass.isAnonymousClass() || klass.isMemberClass() || klass.isLocalClass()) &&
(klass.getModifiers() & Modifier.STATIC) == 0) {
Log.w(TAG, "The following Handler class should be static or leaks might occur: " +
klass.getCanonicalName());
}
}
//使用当前线程的Looper对象
mLooper = Looper.myLooper();
if (mLooper == null) {
throw new RuntimeException(
"Can't create handler inside thread that has not called Looper.prepare()");
}
mQueue = mLooper.mQueue;
mCallback = callback;
}
通过以上三种构造方式就可以为带有消息循环的线程创建一个消息发送工具Handler对象,在构造Handler对象过程中:
在Java层,创建了一个Looper对象,这个Looper对象是用来进入消息循环的,它的内部有一个消息队列MessageQueue对象mQueue;
在JNI层,创建了一个NativeMessageQueue对象,这个NativeMessageQueue对象保存在Java层的消息队列对象mQueue的成员变量mPtr中;
在C++层,创建了一个Looper对象,保存在JNI层的NativeMessageQueue对象的成员变量mLooper中,当Java层的消息队列中没有消息或者C++层没有消息请求,并且被监控的IO接口上没有事件发生,消息循环线程进入等待状态,否则,就唤醒Android应用程序的主线程来处理这个消息。
Java消息发送过程
public final boolean sendMessage(Message msg)
{
return sendMessageDelayed(msg, 0);
}
函数sendMessageDelayed用于延迟发送一个消息,该函数的第二个参数用于指定延时时间,通过sendMessage函数发送的消息的处理时间默认就为当前时间,即表示要马上处理,因此,从sendMessage函数中调用sendMessageDelayed函数,传入的时间参数为0,表示这个消息不要延时处理。
public final boolean sendMessageDelayed(Message msg, long delayMillis)
{
if (delayMillis < 0) {
delayMillis = 0;
}
return sendMessageAtTime(msg, SystemClock.uptimeMillis() + delayMillis);
}
sendMessageAtTime函数用于在指定时间发送一个消息,通过指定的延时时间来计算出消息发送的时间,先获得当前时间,然后加上消息要延时处理的时间,即得到这个处理这个消息的绝对时间,然后调用sendMessageAtTime函数来把消息加入到应用程序的消息队列中去。
public boolean sendMessageAtTime(Message msg, long uptimeMillis)
{
boolean sent = false;
MessageQueue queue = mQueue;
if (queue != null) {
//设置消息处理的目标Handler对象为当前发送消息的Handler对象
msg.target = this;
//将消息压入消息队列
sent = queue.enqueueMessage(msg, uptimeMillis);
}
else {
RuntimeException e = new RuntimeException(
this + " sendMessageAtTime() called with no mQueue");
Log.w("Looper", e.getMessage(), e);
}
return sent;
}
函数首先设置这个消息的目标对象target,即处理这个消息的目标Handler对象:
msg.target = this;
final boolean enqueueMessage(Message msg, long when) {
if (msg.isInUse()) {
throw new AndroidRuntimeException(msg + " This message is already in use.");
}
if (msg.target == null) {
throw new AndroidRuntimeException("Message must have a target.");
}
boolean needWake;
synchronized (this) {
if (mQuiting) {
RuntimeException e = new RuntimeException(msg.target + " sending message to a Handler on a dead thread");
Log.w("MessageQueue", e.getMessage(), e);
return false;
}
msg.when = when;
Message p = mMessages;
//消息队列为空,将消息放在消息队列头上,并且设置需要唤醒消息循环线程
if (p == null || when == 0 || when < p.when) {
// New head, wake up the event queue if blocked.
msg.next = p;
mMessages = msg;
needWake = mBlocked;
} else {
//将消息按时间排序插入到消息队列中
needWake = mBlocked && p.target == null && msg.isAsynchronous();
Message prev;
for (;;) {
prev = p;
p = p.next;
if (p == null || when < p.when) {
break;
}
if (needWake && p.isAsynchronous()) {
needWake = false;
}
}
msg.next = p; // invariant: p == prev.next
prev.next = msg;
}
}
//如果需要唤醒消息循环线程
if (needWake) {
nativeWake(mPtr);
}
return true;
}
当前消息队列为空时,这时候消息循环线程一般就是处于空闲等待状态,这时候就要唤醒它,当消息队列不为空时,这时候就不需要唤醒消息循环线程。通过JNI调用NativeMessageQueue对象的wake函数:
static void android_os_MessageQueue_nativeWake(JNIEnv* env, jobject obj, jint ptr) {
NativeMessageQueue* nativeMessageQueue = reinterpret_cast<NativeMessageQueue*>(ptr);
return nativeMessageQueue->wake();
}
void NativeMessageQueue::wake() {
mLooper->wake();
}
最后通过调用C++的Looper对象的wake函数来唤醒正在睡眠的消息循环线程
void Looper::wake() {
ssize_t nWrite;
do {
nWrite = write(mWakeWritePipeFd, "W", 1);
} while (nWrite == -1 && errno == EINTR);
if (nWrite != 1) {
if (errno != EAGAIN) {
ALOGW("Could not write wake signal, errno=%d", errno);
}
}
}
函数只是通过打开文件描述符mWakeWritePipeFd往管道的写入一个"W"字符串。往管道写入内容的目的是为了唤醒消息循环线程。这里我们知道,对于Java层使用Handler对象发送的消息都是存储在MessageQueue对象中。
Runnable对象发送过程
public final boolean post(Runnable r)
{
return sendMessageDelayed(getPostMessage(r), 0);
}
该函数调用getPostMessage函数将Runnable对象封装为消息Message对象,然后按上述消息发送过程将该消息发送到消息队列中。
private static Message getPostMessage(Runnable r) {
Message m = Message.obtain();
m.callback = r;
return m;
}
将post的Runnable封装为一个消息来处理。
消息循环过程
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;
Binder.clearCallingIdentity();
final long ident = Binder.clearCallingIdentity();
for (;;) {
//不断地从消息队列queue中获取下一个要处理的消息msg
Message msg = queue.next(); // might block
if (msg == null) {
//退出消息循环
return;
}
Printer logging = me.mLogging;
if (logging != null) {
logging.println(">>>>> Dispatching to " + msg.target + " " +
msg.callback + ": " + msg.what);
}
//调用消息对应目标Handler来分发该消息
msg.target.dispatchMessage(msg);
if (logging != null) {
logging.println("<<<<< Finished to " + msg.target + " " + msg.callback);
}
final long newIdent = Binder.clearCallingIdentity();
if (ident != newIdent) {
Log.wtf(TAG, "Thread identity changed from 0x"
+ Long.toHexString(ident) + " to 0x"
+ Long.toHexString(newIdent) + " while dispatching to "
+ msg.target.getClass().getName() + " "
+ msg.callback + " what=" + msg.what);
}
msg.recycle();
}
}
函数首先不断地从消息队列mQueue中去获取下一个要处理的消息msg,如果取得的消息为null,就表示要退出消息循环,否则就要调用这个消息的目标Handler对象的dispatchMessage成员函数来处理这个消息。
final Message next() {
int pendingIdleHandlerCount = -1; // -1 only during first iteration
int nextPollTimeoutMillis = 0;
for (;;) {
if (nextPollTimeoutMillis != 0) {
Binder.flushPendingCommands();
}
//检查有没有消息请求,及被监控的IO接口上没有有事件发生,如果没有,则当前消息循环线程进入睡眠等待状态
nativePollOnce(mPtr, nextPollTimeoutMillis);
//如果mQuiting为false,表示退出消息循环,返回null,从而可以退出loop函数的for循环
synchronized (this) {
if (mQuiting) {
return null;
}
// 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) {
//从消息队列中查找异步消息对象
do {
prevMsg = msg;
msg = msg.next;
} while (msg != null && !msg.isAsynchronous());
}
//如果消息队列中有消息
if (msg != null) {
//当前时间小于消息执行时间
if (now < msg.when) {
//计算下一次轮询等待时间
nextPollTimeoutMillis = (int) Math.min(msg.when - now, Integer.MAX_VALUE);
} else {//当前时间大于或等于消息执行时间
mBlocked = false;
if (prevMsg != null) {
prevMsg.next = msg.next;
} else {
mMessages = msg.next;
}
msg.next = null;
if (false) Log.v("MessageQueue", "Returning message: " + msg);
msg.markInUse();
return msg;
}
} else {
// -1表示下次调用nativePollOnce时,如果消息队列中没有消息,就进入无限等待状态。
nextPollTimeoutMillis = -1;
}
//如果应用程序注册了IdleHandler接口来处理一些事情,那么在进入空闲等待状态前,会先执行这里IdleHandler
if (pendingIdleHandlerCount < 0 && (mMessages == null || now < mMessages.when)) {
pendingIdleHandlerCount = mIdleHandlers.size();
}
//如果没有IdleHandler需要执行,则进入下一次循环
if (pendingIdleHandlerCount <= 0) {
// No idle handlers to run. Loop and wait some more.
mBlocked = true;
continue;
}
if (mPendingIdleHandlers == null) {
mPendingIdleHandlers = new IdleHandler[Math.max(pendingIdleHandlerCount, 4)];
}
mPendingIdleHandlers = mIdleHandlers.toArray(mPendingIdleHandlers);
}
//处理所有注册的IdleHandler
for (int i = 0; i < pendingIdleHandlerCount; i++) {
final IdleHandler idler = mPendingIdleHandlers[i];
mPendingIdleHandlers[i] = null; // release the reference to the handler
boolean keep = false;
try {
keep = idler.queueIdle();
} catch (Throwable t) {
Log.wtf("MessageQueue", "IdleHandler threw exception", t);
}
//如果返回值为false,那么就会从应用程序中移除这个IdleHandler,否则继续维护着这个IdleHandler
if (!keep) {
synchronized (this) {
mIdleHandlers.remove(idler);
}
}
}
pendingIdleHandlerCount = 0;
//While calling an idle handler, a new message could have been delivered
//so go back and look again for a pending message without waiting.
nextPollTimeoutMillis = 0;
}
}
函数首先进入JNI层的nativePollOnce函数检查消息队列中是否有消息,或者被监控的IO接口上是否有事件发送,如果有,则处理相应的消息或事件,否则当前消息循环线程就睡眠等待。
static void android_os_MessageQueue_nativePollOnce(JNIEnv* env, jobject obj,
jint ptr, jint timeoutMillis) {
//通过参数ptr取回在JNI层创建的NatvieMessageQueue对象
NativeMessageQueue* nativeMessageQueue = reinterpret_cast<NativeMessageQueue*>(ptr);
nativeMessageQueue->pollOnce(env, timeoutMillis);
}
继续调用NatvieMessageQueue对象的pollOnce函数
void NativeMessageQueue::pollOnce(JNIEnv* env, int timeoutMillis) {
mInCallback = true;
mLooper->pollOnce(timeoutMillis);
mInCallback = false;
if (mExceptionObj) {
env->Throw(mExceptionObj);
env->DeleteLocalRef(mExceptionObj);
mExceptionObj = NULL;
}
}
inline int pollOnce(int timeoutMillis) {
return pollOnce(timeoutMillis, NULL, NULL, NULL);
}
int Looper::pollOnce(int timeoutMillis, int* outFd, int* outEvents, void** outData) {
int result = 0;
for (;;) {
//遍历已发生的事件请求,并返回该event及该事件的句柄
while (mResponseIndex < mResponses.size()) {
const Response& response = mResponses.itemAt(mResponseIndex++);
int ident = response.request.ident;
if (ident >= 0) {
int fd = response.request.fd;
int events = response.events;
void* data = response.request.data;
if (outFd != NULL) *outFd = fd;
if (outEvents != NULL) *outEvents = events;
if (outData != NULL) *outData = data;
return ident;
}
}
if (result != 0) {
if (outFd != NULL) *outFd = 0;
if (outEvents != NULL) *outEvents = 0;
if (outData != NULL) *outData = NULL;
return result;
}
result = pollInner(timeoutMillis);
}
}
调用pollInner函数来进一步操作,如果pollInner返回值不等于0,这个函数就可以返回了。
int Looper::pollInner(int timeoutMillis) {
// Adjust the timeout based on when the next message is due.
if (timeoutMillis != 0 && mNextMessageUptime != LLONG_MAX) {
nsecs_t now = systemTime(SYSTEM_TIME_MONOTONIC);
int messageTimeoutMillis = toMillisecondTimeoutDelay(now, mNextMessageUptime);
if (messageTimeoutMillis >= 0 && (timeoutMillis < 0 || messageTimeoutMillis < timeoutMillis)) {
timeoutMillis = messageTimeoutMillis;
}
}
// Poll.
int result = ALOOPER_POLL_WAKE;
mResponses.clear();
mResponseIndex = 0;
struct epoll_event eventItems[EPOLL_MAX_EVENTS];
//调用epoll_wait检查epoll专用文件描述符mEpollFd所监控的文件描述符是否有IO事件发生,设置的超时时间为timeoutMillis
int eventCount = epoll_wait(mEpollFd, eventItems, EPOLL_MAX_EVENTS, timeoutMillis);
//如果监控的句柄上有事件产生或者超时时间到时,epoll_wait函数将返回,否则epoll_wait睡眠等待事件发生
mLock.lock();
//如果eventCount小于0,说明监控出错
if (eventCount < 0) {
if (errno == EINTR) {
goto Done;
}
ALOGW("Poll failed with an unexpected error, errno=%d", errno);
result = ALOOPER_POLL_ERROR;
goto Done;
}
// 如果eventCount等于0,就说明是超时了
if (eventCount == 0) {
result = ALOOPER_POLL_TIMEOUT;
goto Done;
}
//如果eventCount大于0,表示有事件发送
for (int i = 0; i < eventCount; i++) {
int fd = eventItems[i].data.fd;
uint32_t epollEvents = eventItems[i].events;
//如果在mWakeReadPipeFd文件描述符上发生了EPOLLIN事件,就说明消息队列里面有新的消息需要处理。因为当其它的线程向消息队列加入新的消息时,会调用Looper类的wake函数向这个管道写入新的内容来通知消息循环线程有新的消息需要处理
if (fd == mWakeReadPipeFd) {
if (epollEvents & EPOLLIN) {
//读取管道中的内容
awoken();
} else {
ALOGW("Ignoring unexpected epoll events 0x%x on wake read pipe.", epollEvents);
}
//如果是其他被监控的句柄产生了某些事件
} else {
//得到该事件句柄在mRequests向量中的索引位置,变量mRequests以键值对的形式保存了所有添加的监控句柄
ssize_t requestIndex = mRequests.indexOfKey(fd);
if (requestIndex >= 0) {
//检查事件类型
int events = 0;
if (epollEvents & EPOLLIN) events |= ALOOPER_EVENT_INPUT;
if (epollEvents & EPOLLOUT) events |= ALOOPER_EVENT_OUTPUT;
if (epollEvents & EPOLLERR) events |= ALOOPER_EVENT_ERROR;
if (epollEvents & EPOLLHUP) events |= ALOOPER_EVENT_HANGUP;
//通过fd从mRequests向量中查找到对应的Request描述符,然后将该描述符与发送的事件封装为Response数据结构,并保存到向量mResponses中
pushResponse(events, mRequests.valueAt(requestIndex));
} else {
ALOGW("Ignoring unexpected epoll events 0x%x on fd %d that is "
"no longer registered.", epollEvents, fd);
}
}
}
Done: ;
//处理C++层的消息
mNextMessageUptime = LLONG_MAX;
//所有C++层的消息都封装为MessageEnvelope类型的变量并保存到mMessageEnvelopes链表中
while (mMessageEnvelopes.size() != 0) {
nsecs_t now = systemTime(SYSTEM_TIME_MONOTONIC);
const MessageEnvelope& messageEnvelope = mMessageEnvelopes.itemAt(0);
//处理当前时刻之前的所有消息
if (messageEnvelope.uptime <= now) {
{
//取出处理该消息的Hanlder
sp<MessageHandler> handler = messageEnvelope.handler;
//取出该消息描述符
Message message = messageEnvelope.message;
//从mMessageEnvelopes链表中移除该消息
mMessageEnvelopes.removeAt(0);
//表示当前消息循环线程正在处理消息,处于唤醒状态,因此消息发送线程无需唤醒消息循环线程
mSendingMessage = true;
mLock.unlock();
//调用该消息Handler对象的handleMessage函数来处理该消息
handler->handleMessage(message);
} // release handler
mLock.lock();
mSendingMessage = false;
result = ALOOPER_POLL_CALLBACK;
} else {
// The last message left at the head of the queue determines the next wakeup time.
mNextMessageUptime = messageEnvelope.uptime;
break;
}
}
// Release lock.
mLock.unlock();
//前面将监控句柄上发送的事件封装为Response对象并保存在mResponses向量中,这里就开始处理这些事件
for (size_t i = 0; i < mResponses.size(); i++) {
Response& response = mResponses.editItemAt(i);
if (response.request.ident == ALOOPER_POLL_CALLBACK) {
int fd = response.request.fd;
int events = response.events;
void* data = response.request.data;
//调用这些句柄的callback回调函数来处理发送的事件
int callbackResult = response.request.callback->handleEvent(fd, events, data);
if (callbackResult == 0) {
removeFd(fd);
}
// Clear the callback reference in the response structure promptly because we
// will not clear the response vector itself until the next poll.
response.request.callback.clear();
result = ALOOPER_POLL_CALLBACK;
}
}
return result;
}
前面介绍到,对于Java层发送的消息,都保存在Java层的MessageQueue对象中,当应用程序向消息循环线程中发送一个Java消息后,通过管道方式通知正在睡眠等待的消息循环线程,消息循环线程接收到管道事件后,从C++层返回到Java层处理Java消息。Android的消息循环机制Looper不仅可以处理Java层消息,同时可以处理native层的消息,所有的native消息都被封装为MessageEnvelope对象,并保存在Looper的成员变量mMessageEnvelopes向量中。同时Looper对外提供了addFd接口函数,应用程序可以通过该接口向消息循环线程添加一个需要监控的文件句柄,并注册事件处理回调函数,从而可以在监听到该句柄上的事件时,回调事件处理函数来处理相应的事件。
void Looper::awoken() {
char buffer[16];
ssize_t nRead;
do {
//读取管道内容
nRead = read(mWakeReadPipeFd, buffer, sizeof(buffer));
} while ((nRead == -1 && errno == EINTR) || nRead == sizeof(buffer));
}
当读取完管道内容后,应用程序就可以发送一个Java消息到消息队列中,并再次通过写管道方式来通知正在睡眠等待的消息循环线程返回到Java层去处理消息。
Java消息处理过程
msg.target.dispatchMessage(msg);
这里调用发送消息Handler类的dispatchMessage函数来分发该消息,在 前面介绍Hanlder发送消息时,被发送的消息msg的target被设置为发送该消息的Handler对象:
public void dispatchMessage(Message msg) {
//如果handler发送的是一个Runnable对象消息,
if (msg.callback != null) {
handleCallback(msg);
} else {
//如果在构造handler对象时指定了Callback对象,则调用该Callback对象的handleMessage函数来处理消息
if (mCallback != null) {
if (mCallback.handleMessage(msg)) {
return;
}
}
//调用handler对象的handleMessage函数来处理消息
handleMessage(msg);
}
}
当Hanlder对象发送的是一个Runnable对象时,发送过程中实际上是将其封装为一个消息对象来发送的,只是在处理该消息的时候自动调用Runnable接口所实现的方法:
private static void handleCallback(Message message) {
message.callback.run();
}
从Java消息处理过程我们可以总结如下:
监控文件描述符注册过程
int Looper::addFd(int fd, int ident, int events, ALooper_callbackFunc callback, void* data) {
return addFd(fd, ident, events, callback ? new SimpleLooperCallback(callback) : NULL, data);
}
该函数将事件处理回调函数封装为SimpleLooperCallback对象,并调用另一个addFd函数将Socket接收端描述符添加到消息循环中监听:
int Looper::addFd(int fd, int ident, int events, const sp<LooperCallback>& callback, void* data) {
if (!callback.get()) {
if (! mAllowNonCallbacks) {
ALOGE("Invalid attempt to set NULL callback but not allowed for this looper.");
return -1;
}
if (ident < 0) {
ALOGE("Invalid attempt to set NULL callback with ident < 0.");
return -1;
}
} else {
ident = ALOOPER_POLL_CALLBACK;
}
//设置监听的事件类型
int epollEvents = 0;
if (events & ALOOPER_EVENT_INPUT) epollEvents |= EPOLLIN;
if (events & ALOOPER_EVENT_OUTPUT) epollEvents |= EPOLLOUT;
{ // acquire lock
AutoMutex _l(mLock);
//将请求监听的文件描述符封装为Request对象
Request request;
request.fd = fd;
request.ident = ident;
//callback注册为SimpleLooperCallback对象
request.callback = callback;
request.data = data;
//初始化一个事件描述符
struct epoll_event eventItem;
memset(& eventItem, 0, sizeof(epoll_event)); // zero out unused members of data field union
eventItem.events = epollEvents;
eventItem.data.fd = fd;
//以文件描述符为键从mRequests中查找对应的Request对象
ssize_t requestIndex = mRequests.indexOfKey(fd);
//如果添加的Request不存在,则向mEpollFd添加一个事件项
if (requestIndex < 0) {
int epollResult = epoll_ctl(mEpollFd, EPOLL_CTL_ADD, fd, & eventItem);
if (epollResult < 0) {
ALOGE("Error adding epoll events for fd %d, errno=%d", fd, errno);
return -1;
}
//将创建的Request对象以键值对的形式保存到Looper的成员变量mRequests中
mRequests.add(fd, request);
} else {
//如果添加的Request已经存在,则修改该事件项
int epollResult = epoll_ctl(mEpollFd, EPOLL_CTL_MOD, fd, & eventItem);
if (epollResult < 0) {
ALOGE("Error modifying epoll events for fd %d, errno=%d", fd, errno);
return -1;
}
//使用当前的request替换原有的request对象
mRequests.replaceValueAt(requestIndex, request);
}
} // release lock
return 1;
}
函数首先创建一个Request对象来描述注册的Socket接收端文件描述符及其对应的回调函数,然后将创建的Request对象添加到Looper的成员变量mRequests中,同时使用epoll_ctl系统调用将Socket接收端文件描述符添加到epoll监听中。Request数据结构定义如下:
struct Request {
int fd; //被监控的设备句柄
int ident;
sp<LooperCallback> callback; //该句柄下发生事件的回调函数
void* data;
};
当添加到消息循环Looper监控的文件句柄上有事件发生时,将发生的事件及对应的请求封装为Response对象,Response数据结构定义如下:
struct Response {
int events; //事件
Request request;//监控请求对象
};
同时添加到Looper成员变量mResponses中等候处理:
void Looper::pushResponse(int events, const Request& request) {
Response response;
response.events = events;
response.request = request;
mResponses.push(response);
}
事件处理最终由注册的回调函数来完成:
int callbackResult = response.request.callback->handleEvent(fd, events, data);
Native消息发送过程
void Looper::sendMessage(const sp<MessageHandler>& handler, const Message& message) {
nsecs_t now = systemTime(SYSTEM_TIME_MONOTONIC);
sendMessageAtTime(now, handler, message);
}
调用sendMessageAtTime函数来指定消息的执行时间,这里将消息的执行时间设置为当前时间
void Looper::sendMessageAtTime(nsecs_t uptime, const sp<MessageHandler>& handler,
const Message& message) {
size_t i = 0;
{ // acquire lock
AutoMutex _l(mLock);
size_t messageCount = mMessageEnvelopes.size();
//从消息队列中查找当前消息执行时间大于其他消息执行时间的位置,即按消息执行时间排序
while (i < messageCount && uptime >= mMessageEnvelopes.itemAt(i).uptime) {
i += 1;
}
//将消息,消息处理Handler等封装为MessageEnvelope对象
MessageEnvelope messageEnvelope(uptime, handler, message);
//将创建的MessageEnvelope对象插入到消息队列mMessageEnvelopes中
mMessageEnvelopes.insertAt(messageEnvelope, i, 1);
//如果当前消息循环线程正处于唤醒状态,则返回,否则唤醒消息循环线程
if (mSendingMessage) {
return;
}
} // release lock
//如果消息循环线程正处于睡眠状态,则唤醒消息循环线程
if (i == 0) {
wake();
}
}
该函数将消息封装为MessageEnvelope对象,并按时间顺序插入到消息队列mMessageEnvelopes中,MessageEnvelope类型封装了消息及消息对应的处理Handler,其定义如下:
struct MessageEnvelope {
MessageEnvelope() : uptime(0) { }
MessageEnvelope(nsecs_t uptime, const sp<MessageHandler> handler,
const Message& message) : uptime(uptime), handler(handler), message(message) {
}
//消息处理时间
nsecs_t uptime;
//消息处理Handler对象
sp<MessageHandler> handler;
//消息对象
Message message;
};
native消息发送过程就是将消息封装为MessageEnvelope对象并插入到消息循环Looper的成员变量mMessageEnvelopes中,前面介绍的消息循环过程中,消息循环线程通过遍历消息队列mMessageEnvelopes来处理队列中的所有消息
//所有C++层的消息都封装为MessageEnvelope类型的变量并保存到mMessageEnvelopes链表中
while (mMessageEnvelopes.size() != 0) {
nsecs_t now = systemTime(SYSTEM_TIME_MONOTONIC);
const MessageEnvelope& messageEnvelope = mMessageEnvelopes.itemAt(0);
//处理当前时刻之前的所有消息
if (messageEnvelope.uptime <= now) {
{
//取出处理该消息的Hanlder
sp<MessageHandler> handler = messageEnvelope.handler;
//取出该消息描述符
Message message = messageEnvelope.message;
//从mMessageEnvelopes链表中移除该消息
mMessageEnvelopes.removeAt(0);
//表示当前消息循环线程正在处理消息,处于唤醒状态,因此消息发送线程无需唤醒消息循环线程
mSendingMessage = true;
mLock.unlock();
//调用该消息Handler对象的handleMessage函数来处理该消息
handler->handleMessage(message);
} // release handler
mLock.lock();
mSendingMessage = false;
result = ALOOPER_POLL_CALLBACK;
} else {
// The last message left at the head of the queue determines the next wakeup time.
mNextMessageUptime = messageEnvelope.uptime;
break;
}
}
1.Android应用程序的消息处理机制由消息循环、消息发送和消息处理三个部分组成的。
2.消息循环线程通过Linux系统的Epoll机制中的epoll_wait函数失眠等待消息到来;
3.当应用程序向消息循环线程发送一个Java消息时,通过管道方式唤醒消息循环线程,并返回Java层处理消息;
4.当应用程序向消息循环线程发送一个Native消息时,仍然通过管道方式唤醒消息循环线程;
5.消息循环线程不仅可以处理消息,同时可以监控并处理指定设备句柄上发送的事件;