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> 处理消息的过程中,线程被阻塞
一旦消息队列所在的线程被阻塞,该消息队列就无法执行任何消息,因为消息队列是逐个处理消息的,因此在处理消息队列中的消息的过程中,一是尽量不合其他工作线程共享同步锁,而是处理消息的过程中不要陷入无限循环或者无法返回,即使消息陷入无限循环,也需要有让消息返回的方式。
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> 处理消息的过程中,线程被阻塞
一旦消息队列所在的线程被阻塞,该消息队列就无法执行任何消息,因为消息队列是逐个处理消息的,因此在处理消息队列中的消息的过程中,一是尽量不合其他工作线程共享同步锁,而是处理消息的过程中不要陷入无限循环或者无法返回,即使消息陷入无限循环,也需要有让消息返回的方式。
相关文章推荐
- Android消息队列(二)--异步消息处理
- android开发教程之使用looper处理消息队列
- Android消息队列(三)--多线程与消息处理
- 《Android系统学习》第十章:Android消息处理、消息循环和消息队列
- 关于android Handler进行线程处理消息队列与线程队列线程无法停止的问题
- android的定时及消息队列处理
- 当主线程队列,如果处理一个消息超过5秒,android 就会抛出一个 ANP(无响应)的消息
- Android消息处理机制(二):循环和消息队列的创建
- Android之使用looper处理消息队列
- Android 系列 4.11使用活动线程队列和处理程序在线程之间发送消息
- Android应用程序消息处理机制(Looper、Handler)分析
- Android--利用Handler消息转发机制实现倒计时(内含防止内存泄露处理)
- 学习笔记:android中Handler异步消息处理机制
- android的消息处理机制(图+源码分析)——Looper,Handler,Message
- android的消息处理机制(图+源码分析)——Looper,Handler,Message
- Android-Volley网络通信框架(二次封装数据请求和图片请求(包括处理请求队列和图片缓存))
- Android 异步消息处理机制 让你深入理解 Looper、Handler、Message三者关系
- Android 异步消息处理机制 让你深入理解 Looper、Handler、Message三者关系
- Android异步消息处理机制完全解析,带你从源码的角度彻底理解
- View的post方法到底干了啥,深入分析Android异步消息处理机制