您的位置:首页 > 移动开发 > Android开发

Android消息队列处理消息

2013-12-19 14:08 141 查看
Looper中的MessageQueue中持有一个mMessages的对象,用于保存,它所获得的消息对象。Looper通过,它的next方法进行消息循环,如果发现了消息,就将mMessages 交给对应的target 处理

Message next() {

int pendingIdleHandlerCount = -1; // -1 only during first iteration

int nextPollTimeoutMillis = 0;

for (;;) {

if (nextPollTimeoutMillis != 0) {

Binder.flushPendingCommands();

}

// We can assume mPtr != 0 because the loop is obviously still running.

// The looper will not call this method after the loop quits.

nativePollOnce(mPtr, 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());

}

if (msg != null) {

if (now < msg.when) {

// Next message is not ready. Set a timeout to wake up when it is ready.

nextPollTimeoutMillis = (int) Math.min(msg.when - now, Integer.MAX_VALUE);

} else {

// Got a message.

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 {

// No more messages.

nextPollTimeoutMillis = -1;

}

// Process the quit message now that all pending messages have been handled.

if (mQuitting) {

dispose();

return null;

}

// If first time idle, then get the number of idlers to run.

// Idle handles only run if the queue is empty or if the first message

// in the queue (possibly a barrier) is due to be handled in the future.

if (pendingIdleHandlerCount < 0

&& (mMessages == null || now < mMessages.when)) {

pendingIdleHandlerCount = mIdleHandlers.size();

}

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);

}

// Run the idle handlers.

// We only ever reach this code block during the first iteration.

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);

}

if (!keep) {

synchronized (this) {

mIdleHandlers.remove(idler);

}

}

}

// Reset the idle handler count to 0 so we do not run them again.

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;

}

}

如果 nativePollOnce(mPtr, nextPollTimeoutMillis),能够返回,那么mMessages 才有可能被处理,现在有两个问题。

<1> mMessages什么时候被赋值

mMessages有值,那肯定是有消息被放入,消息是通过Handler 放入的,它调用Looper的MessageQueue的enqueueMessage,方法将消息数据放入MessageQueue,并向native 层的Looper的管道写入数据,epoll发现数据,使得nativePollOnce能够返回,从而mMessages能够在Looper.loop()中处理。

<2> 处理消息的过程中,线程被阻塞

一旦消息队列所在的线程被阻塞,该消息队列就无法执行任何消息,因为消息队列是逐个处理消息的,因此在处理消息队列中的消息的过程中,一是尽量不合其他工作线程共享同步锁,而是处理消息的过程中不要陷入无限循环或者无法返回,即使消息陷入无限循环,也需要有让消息返回的方式。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: 
相关文章推荐