Android中消息机制中一些细节知识点
16lz
2021-12-04
时隔很久,重温Android消息机制,注意到这么两个东西
MessageQueue中的IdleHandler
看MessageQueue的源码发现,里面有个IdleHandler,声明如下
/** * Callback interface for discovering when a thread is going to block * waiting for more messages. */ public static interface IdleHandler { /** * Called when the message queue has run out of messages and will now * wait for more. Return true to keep your idle handler active, false * to have it removed. This may be called if there are still messages * pending in the queue, but they are all scheduled to be dispatched * after the current time. * 在当前线程变为空闲状态的时候执行,返回值代表是否保留该对象,如果返回false,那么该对象执行一次之后会被移除。 */ boolean queueIdle(); }
它体现在MessageQueue.next()方法中。
Message next() { // 省略部分代码 int pendingIdleHandlerCount = -1; // -1 only during first iteration for (;;) { if (nextPollTimeoutMillis != 0) { Binder.flushPendingCommands(); } nativePollOnce(ptr, nextPollTimeoutMillis); synchronized (this) { // 省略部分代码 // 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); }// end of synchronized (this) // 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) {// 由此可见,IdleHandler返回值的作用 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; } }
注意,这个IdleHandler的执行是每调用一次next()方法才会执行一次。
那么这个类的用处就显而易见了,当我们需要在线程空闲时执行一些操作的话,就可以利用这个类来做。使用方式如下
Looper.myQueue().addIdleHandler(new MessageQueue.IdleHandler() { @Override public boolean queueIdle() { // do something return false; } });
MessageQueue中的同步阻塞器
其实,同步阻塞器的本质依旧是一个Message,只不过它的target为空。它存在于消息队列中。同步阻塞器在插入后会返回一个token值,移除则是通过token值来进行。插入和移除的过程就不看了,它正常消息的插入移除很相似,都需要在消息队列中寻找一个合适的位置进行插入。看看它在消息队列中生效的地方。依旧看next()方法
Message next() { // 省略部分代码 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 && msg.target == null) { // msg.target == null 就代表该msg是同步阻塞器。正常通过Handler发送的消息msg.target都不可能为空的。 // Stalled by a barrier. Find the next asynchronous message in the queue. do { // 如果走到这里,则需要找一个异步的消息,Message的同步与异步的差别在这里就体现出来了,同步的消息会受阻塞器的影响,而异步消息不会。 prevMsg = msg; msg = msg.next; } while (msg != null && !msg.isAsynchronous()); } if (msg != null) {// 这里的msg不可能是同步阻塞器。 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) {// 代表着得到的msg是异步消息 prevMsg.next = msg.next; } else { mMessages = msg.next; } msg.next = null; if (false) Log.v("MessageQueue", "Returning message: " + msg); return msg; } } else { // No more messages. nextPollTimeoutMillis = -1; } // 省略部分代码 }// end of synchronized (this) // 省略部分代码 } }
这里我们要注意一点,同步阻塞器是无法阻塞在阻塞器生效前的同步消息。所以,当某个消息队列被阻塞器阻塞之后,要想执行操作,就需要你移除阻塞器或者发送异步消息。
更多相关文章
- Handler,Looper,MessageQueue的实现
- Android(安卓)线程同步 ConditionVariable的用法
- Android的状态栏通知(Notification)
- Version Code 版本设置
- Android聊天室(源码)
- Android(安卓)蓝牙(BLE)连接,发送,接收消息
- Android(安卓)MQTT
- Android(安卓)MediaPlayer 字幕同步
- Android(安卓)Camera 数据流